将多个graphic2d组件绘制到JPanel中

时间:2015-06-24 17:39:14

标签: 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();
            }
        });     

    }
}

3 个答案:

答案 0 :(得分:3)

您的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);
   }

}

答案 1 :(得分:1)

您不应该通过添加组件来绘制线条。组件是面板,按钮等。

请参阅本教程,了解如何使用Graphics2D进行绘制:https://docs.oracle.com/javase/tutorial/2d/geometry/primitives.html

答案 2 :(得分:-1)

您的代码添加了三个组件,但面板不够大,无法显示其他两个组件

    panel.setPreferredSize(new Dimension(200, 600));
    setSize(250, 800);