点击按钮时将形状添加到JPanel

4

我有一个类Circle,其中包含一个按钮和一个jPanel。当单击该按钮时,将在面板上绘制一个圆形,并且每次单击该按钮并更改x和y("某种方式未在此处实现")时,JPanel上会重复出现一个圆形。 如何实现这一点,或者是否有一种方法可以实现我的描述,而不考虑我的代码,但我希望类circle扩展自Shape。

public class Window{

  private JFrame frame;
  private JPanel panel = new JPanel();
  Circle c = new Circle(frame, panel);
  // some other buttons 
  .
  .
 // some code to set the panel grid bag constaraints and background then
 frame.getContentPane().add(panel, gbc_panel);
}

然后是 Circle 类。
public class Circle extends Shape implements ActionListener{

  private JPanel Panel;
  private GridBagConstraints gbc_btnCircle;
  private JButton btnCircle;

  public void setPanel(JPanel panel) {
      Panel = panel;
  }

 public Circle(JFrame frame, JPanel panel){
    btnCircle = new JButton("Circle");
    // some code to set grid bag constraint then
    frame.getContentPane().add(btnCircle, gbc_btnCircle);
    setPanel(panel);        
    btnCircle.addActionListener(this);

 }

  public void paint(Graphics g) {
      super.paintComponents(g);
      g.setColor(Color.red);        
      g.fillOval(100, 100, 100, 100);     
      Panel.add(this);
  }

  public void actionPerformed(ActionEvent arg0) {
    repaint();      
  }
}
2个回答

6

您的理解有些偏差。在您的绘图面板中,应该有一个List<Circle>。然后在绘图面板的paintComponent方法中,您需要遍历该列表以依次绘制每个圆。

class Circle {
    int x, int y, int width, int height;
    public Circle (int x, int y, int width, int height) {
        ... set em
    }
    public void draw(Graphics g) {
        g.fillOval(x, y, width, height);
    }
}
class DrawingPanel extends JPanel {
    List<Circle> circles = new ArrayList<>();

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Circle circle : circles) {
            circle.draw(g);
        }
    }

    // Dont forget to override public Dimension getPreferredSize()
}

要将更多的圆添加到列表中,只需在DrawingPanel类中添加一个addCircle方法

public void addCircle(Circle circle) {
    circles.add(circle);
    repaint();
}

就按钮而言,您应该在 Window 类中创建它。在 ActionListener 中,只需创建一个 new Circle 并通过调用 addCircle 方法将其添加到 DrawingPanel 中即可。
另外,Circle 不需要扩展 ShapeShape API 已经有一个 Ellipse2D 类,您可以从中创建圆形。
class DrawingPanel extends JPanel {
    List<Ellipse2D> circles = new ArrayList<>();

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g.create();
        for (Ellipse2D circle : circles) {
            g2.fill(circle);
        }
        g2.dispose();
    }
    // Dont forget to override public Dimension getPreferredSize()
}

更新:完整示例

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CirclesDemo {

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

    public CirclesDemo() {
        JFrame frame = new JFrame();
        frame.add(panel);
        frame.add(createButton(), BorderLayout.PAGE_END);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private final DrawingPanel panel = new DrawingPanel();

    private JButton createButton() {
        JButton button = new JButton("Add Circle");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                int[] circleValues = generateRandomValues(300, 300, 50, 150);
                int x = circleValues[0];
                int y = circleValues[1];
                int width = circleValues[2];
                int height = width;
                Circle circle = new Circle(x, y, width, height);
                panel.addCircle(circle);
            }
        });
        return button;
    }

    private int[] generateRandomValues(int maxX, int maxY, 
                                       int minSize, int maxSize) {
        Random random = new Random();
        int[] values = new int[3];
        values[0] = random.nextInt(maxX);
        values[1] = random.nextInt(maxY);
        values[2] = Math.min(random.nextInt(maxSize) + minSize, maxSize);
        return values;
    }

    class Circle {

        int x, y, width, height;

        public Circle(int x, int y, int width, int height) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }

        public void draw(Graphics g) {
            g.drawOval(x, y, width, height);
        }
    }

    class DrawingPanel extends JPanel {

        List<Circle> circles = new ArrayList<>();

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Circle circle : circles) {
                circle.draw(g);
            }
        }

        public void addCircle(Circle circle) {
            circles.add(circle);
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }
    }
}

请您帮我看一下这些修改,告诉我为什么还是不起作用?当我点击按钮时,面板上没有任何反应。 - Alaa Othman
  1. 我没有看到按钮在哪里创建以及你添加了 ActionListener。我假设你完全放弃了第一个 Circle 类。
  2. 你是否覆盖了 getPreferredSize
  3. 我没有看到你将 DrawingPanel 添加到框架中。
- Paul Samsotha

1
你正在覆盖Circle的paint方法。你需要覆盖panel的paint方法。

请问如何做到这一点? - Alaa Othman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接