初学者 Graphics2D Java:重绘()

Beginner Graphics2D Java : repaint()

我试图在 Action 处理程序中更改我的红色圆圈的颜色,然后 repaint() 我无法弄清楚为什么它不起作用。

这里进口

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;

我的 class 在这里:

public class CirclePanel extends JPanel implements ActionListener  {
    static JFrame f;
    static JButton run1, run2, reset, quit;
    static JPanel btnPanel;
    static CirclePanel circlePanel;
    static final int NUM = 5;
    static Color c;
    static Graphics2D g2;
    static Graphics2D g3; 

    public CirclePanel(){

        f = new JFrame();

        f.setTitle("Dining Philosophers");
        f.setDefaultCloseOperation(EXIT_ON_CLOSE);
        f.setSize(1000,1000);
        f.setLayout(new BorderLayout());

        btnPanel = new JPanel();
        btnPanel.setPreferredSize(new Dimension(250, 100));
        btnPanel.add(run1 = new JButton("Run 1"));
        btnPanel.add(run2 = new JButton("Run 2"));
        btnPanel.add(reset = new JButton("Reset"));
        btnPanel.add(quit = new JButton("Quit"));

        run1.setPreferredSize(new Dimension(180, 50));
        run2.setPreferredSize(new Dimension(180, 50));
        reset.setPreferredSize(new Dimension(180, 50));
        quit.setPreferredSize(new Dimension(180, 50));

        run1.addActionListener(this);


        f.add(btnPanel, BorderLayout.SOUTH);

        f.add(this, BorderLayout.CENTER);

        f.setVisible(true);
    }


    @Override
    public void paintComponent(Graphics g){

        super.paintComponent(g);
        g2 = (Graphics2D) g;
        g3 = (Graphics2D) g;
        g2.translate(470, 400);

        c = Color.red;

        for(int i = 0; i <  NUM; ++i){
            c = Color.red;

            g2.setColor( c);

            g2.fillOval(150, 0, 100, 100);

            g3.setColor(Color.BLACK);
            g3.fillOval(90, 0, 30, 30);

            g2.rotate(2*Math.PI/ NUM);
        }
    }

如您所见,当我按下按钮 Run1 时,它确实进入了动作处理程序并执行了重绘方法,但没有任何变化。

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == run1) {
            System.out.println("Entered Action Handler");

            g2.setColor(Color.green);

            repaint();

        }
    }

这是我的主要内容:

    public  static void main(String[] args) {

         new CirclePanel();
    }

}

Graphics 对象寿命不长,不稳定,您不应该以这种方式使用它们。不要设置 g2 或任何其他图形 字段 ,而是创建一个名为 Color circleColor = ...; 的颜色字段,然后更改 this。在 protected void paintComponent(Graphics g) 方法中,调用 g.setColor(circleColor);,这应该有效。

删除这些字段,因为它们很危险:

// static Graphics2D g2;
// static Graphics2D g3; 

此外,您的代码显示过度使用静态修饰符,我冒昧地建议您的 none 个字段应该是静态的,除了常量:

static final int NUM

repaint() 方法最终会调用面板的 paintComponent() 方法。 Swing会传入Graphics对象来进行绘画。

在绘画代码中,您总是将颜色硬编码为红色。不要这样做。

相反,您需要在面板中定义一个变量 class。比方说 "circleColor"(即 "circleColor" 替换您的 "c" 变量,因为变量名称应该更具描述性,而不仅仅是单个字符)。

然后在您的 ActionListener 代码中执行:

//g2.setColor(Color.green);
circleColor = Color.green;

你在 paintCompnent() 方法中这样做:

//c = Color.red;
g.setColor(circleColor);

另外:

static Graphics2D g2;
static Graphics2D g3; 

不需要任何这些变量。您始终使用传递给绘画方法的 Graphics 对象。

阅读有关 Custom Painting 的 Swing 教程部分,了解更多信息以及有关如何构建代码的更好示例。例如,您不应该使用静态变量。

发生的事情是:

  • 您正在更改动作侦听器中的 g2 颜色。
  • 然后你调用 repaint(); 所以 paintComponent(Graphics g) 被调用。
  • paintComponent(Graphics g) 方法中,您将 g2 颜色设置为 c,以便覆盖您在动作侦听器中所做的更改。

这就是为什么圆圈最终没有改变颜色的原因。

您应该在构造函数中而不是在for 循环中设置c = Color.RED;,然后您只需在动作侦听器c = Color.GREEN; 中更改c 的值即可。

此外,您在 for 循环中和循环之前都设置了 c = Color.RED;,这是无用的。

编辑:
正如 @camickr 所建议的那样,您的代码结构也很糟糕。

  • 您不需要 g2g3 因为您可以绘制多个形状 使用相同的 Graphics g 对象。
  • 在你的情况下,你甚至不需要在 paintComponent 方法之外调用 g,因为你可以像我上面说的那样简单地更改 Color c 变量。
  • 您也不需要所有这些 static 变量。只需将它们设为 private,如果您需要从 class 外部访问它们,您应该创建一些 getterssetters.

Here you'll find more on static variables and some examples.
Here you'll find more about getters, setters and encapsulation.

如何更改代码的示例:

public class CirclePanel extends JPanel implements ActionListener  {

    private JFrame f;
    private JButton run1, run2, reset, quit;
    private JPanel btnPanel;
    private int NUM;
    private Color c;

    public CirclePanel(){

        color1 = Color.red;
        color2 = Color.black;

        NUM = 5;

        // Setup JFrame and stuff as you were doing.

    }


    @Override
    public void paintComponent(Graphics g){

        super.paintComponent(g);

        g.translate(470, 400);

        for(int i = 0; i < NUM; i++){

            g.setColor(color1);
            g.fillOval(150, 0, 100, 100);

            g.setColor(color2);
            g.fillOval(90, 0, 30, 30);

            g.rotate(2*Math.PI/ NUM);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == run1) {
            System.out.println("Entered Action Handler");

            color1 = Color.green;

            repaint();
        }
    }

    // GETTERS and SETTERS if needed
}