java - 将多个 graphic2d 组件绘制到 JPanel 中

标签 java swing graphics2d jcomponent

我已经阅读了很多关于绘制 Graphics2D 组件和添加到 JPanel/JFrame 的教程,但我找不到如何简单地将多个这些组件添加到一个 JPanel 中。我下面的代码只添加了 1 个组件(行),我找不到为什么不能添加更多组件。

我做错了什么?

enter image description here

期望的行为:应该有 3 条红线。

我的整个代码:

package Examples;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Example1 extends JFrame {

    private final JPanel panel;

    public Example1() {

        // jpanel with graphics
        panel = new JPanel();
        panel.setPreferredSize(new Dimension(200, 200));
        panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        panel.setBackground(Color.WHITE);
        add(panel);


        // adding lines to jpanel
        AddMyLine(); // 1st: this works well
        AddMyLine(); // 2nd: this doesn't work
        AddMyLine(); // 3rd: this doesn't work


        setLayout(new FlowLayout(FlowLayout.LEFT));
        setSize(250, 250);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        setLocationRelativeTo(null);
    }


    // add new line to jpanel
    private void AddMyLine() {
        MyLine c = new MyLine();
        System.out.println(c);
        panel.add(c);
    }



    // line component
    private class MyLine extends JComponent {

        public MyLine() {
            setPreferredSize(new Dimension(200, 200));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            g2d.setColor(Color.red);
            g2d.setStroke(new BasicStroke(1));
            int x1 = (int)Math.round(Math.random()*200);
            int y1 = (int)Math.round(Math.random()*200);
            int x2 = (int)Math.round(Math.random()*200);
            int y2 = (int)Math.round(Math.random()*200);
            g2d.drawLine(x1,y1,x2,y2);
        }
    }


    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example1();
            }
        });     

    }
}

最佳答案

您的 MyLine 类不应是 Swing 组件,因此不应扩展 JComponent。相反,它应该是一个逻辑实体,实际上可以是实现 Shape 的东西,例如 Line2D,或者可以是您自己的完整类,但应该知道如何绘制自己,即,如果它不实现 Shape,那么它应该有一些其他类可以调用的 draw(Graphics2D g) 方法。相反,我认为您应该致力于扩展面板的 JPanel 类,这样您就可以覆盖它的 paintComponent 方法,给它一个集合来保存添加到它的任何 MyLine 项目,并在 paintComponent 中绘制 MyLine 项目。

其他选项包括直接绘制到 BufferedImage,然后在 JPanel 的 paintComponent 方法中显示该 BufferedImage。这非常适合静态图像,但不适合需要更改或移动的图像。

例如,

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

public class DrawChit extends JPanel {
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;
   private List<Shape> shapes = new ArrayList<>();

   public DrawChit() {
      setBackground(Color.white);
   }

   public void addShape(Shape shape) {
      shapes.add(shape);
      repaint();
   }

   @Override // make it bigger
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      for (Shape shape : shapes) {
         g2.draw(shape);
      }
   }

   private static void createAndShowGui() {
      DrawChit drawChit = new DrawChit();

      drawChit.addShape(new Line2D.Double(10, 10, 100, 100));
      drawChit.addShape(new Ellipse2D.Double(120, 120, 200, 200));

      JFrame frame = new JFrame("DrawChit");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(drawChit);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

或者使用我自己的 MyDrawable 类的示例,它生成如下所示的 GUI:

enter image description here

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class DrawChit extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;
   private List<MyDrawable> drawables = new ArrayList<>();

   public DrawChit() {
      setBackground(Color.white);
   }

   public void addMyDrawable(MyDrawable myDrawable) {
      drawables.add(myDrawable);
      repaint();
   }

   @Override
   // make it bigger
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      for (MyDrawable myDrawable : drawables) {
         myDrawable.draw(g2);
      }
   }

   public void clearAll() {
      drawables.clear();
      repaint();
   }

   private static void createAndShowGui() {
      final List<MyDrawable> myDrawables = new ArrayList<>();
      myDrawables.add(new MyDrawable(new Line2D.Double(100, 40, 400, 400),
            Color.red, new BasicStroke(40)));
      myDrawables.add(new MyDrawable(new Ellipse2D.Double(50, 10, 400, 400),
            Color.blue, new BasicStroke(18)));
      myDrawables.add(new MyDrawable(new Rectangle2D.Double(40, 200, 300, 300),
            Color.cyan, new BasicStroke(25)));
      myDrawables.add(new MyDrawable(new RoundRectangle2D.Double(75, 75, 490, 450, 40, 40),
            Color.green, new BasicStroke(12)));

      final DrawChit drawChit = new DrawChit();

      JFrame frame = new JFrame("DrawChit");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(drawChit);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);

      int timerDelay = 1000;
      new Timer(timerDelay, new ActionListener() {
         private int drawCount = 0;

         @Override
         public void actionPerformed(ActionEvent e) {
            if (drawCount >= myDrawables.size()) {
               drawCount = 0;
               drawChit.clearAll();
            } else {
               drawChit.addMyDrawable(myDrawables.get(drawCount));
               drawCount++;
            }
         }
      }).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class MyDrawable {
   private Shape shape;
   private Color color;
   private Stroke stroke;

   public MyDrawable(Shape shape, Color color, Stroke stroke) {
      this.shape = shape;
      this.color = color;
      this.stroke = stroke;
   }

   public Shape getShape() {
      return shape;
   }

   public Color getColor() {
      return color;
   }

   public Stroke getStroke() {
      return stroke;
   }

   public void draw(Graphics2D g2) {
      Color oldColor = g2.getColor();
      Stroke oldStroke = g2.getStroke();

      g2.setColor(color);
      g2.setStroke(stroke);
      g2.draw(shape);

      g2.setColor(oldColor);
      g2.setStroke(oldStroke);
   }

   public void fill(Graphics2D g2) {
      Color oldColor = g2.getColor();
      Stroke oldStroke = g2.getStroke();

      g2.setColor(color);
      g2.setStroke(stroke);
      g2.fill(shape);

      g2.setColor(oldColor);
      g2.setStroke(oldStroke);
   }

}

关于java - 将多个 graphic2d 组件绘制到 JPanel 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31033359/

相关文章:

java - 关闭背景图像触摸 libgdx 上的对话框

java - var-arg 方法中的方法重写

java - 非法前向引用 netbeans swing

java - 使用java中的JOptionPane是否可以同时显示多个弹出窗口?

c++ - 如何以编程方式生成与这些相似的形状?

java - super.paint() 在图像上不可见

java - 使用ttf字体使文本宽度灵活

java - 以编程方式进行 Dialogflow 身份验证 java

java - 将字母数字字符串转换为 double

java - 将图像从文件夹拖放到 JTextPane