Java中的事件处理未按预期工作

Java中的事件处理未按预期工作,java,swing,event-handling,Java,Swing,Event Handling,我无法让下面链接的代码完全执行我希望它执行的操作 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Gui { static JFrame frame; static JLabel label; public static void main (String[] args) { Gui gui = new Gui(); gui.

我无法让下面链接的代码完全执行我希望它执行的操作

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Gui {

    static JFrame frame;
    static JLabel label;

    public static void main (String[] args) {
        Gui gui = new Gui();
        gui.go();
    }

    public void go () {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,300);
        frame.setVisible(true);

        MyDrawPanel panel = new MyDrawPanel();
        frame.getContentPane().add(BorderLayout.CENTER, panel);

        label = new JLabel("I'm a label");
        frame.getContentPane().add(BorderLayout.WEST, label);

        JButton colorButton = new JButton("Change Colors");
        ColorButtonListener colorButtonListener = new ColorButtonListener();
        colorButton.addActionListener(colorButtonListener); 
        frame.getContentPane().add(BorderLayout.SOUTH, colorButton);

        JButton labelButton = new JButton("Change Label");
        LabelButtonListener labelButtonListener = new LabelButtonListener();
        labelButton.addActionListener(labelButtonListener); 
        frame.getContentPane().add(BorderLayout.EAST, labelButton);
    }
}

class ColorButtonListener implements ActionListener {
    JFrame frame = Gui.frame;
    public void actionPerformed (ActionEvent event) {
        frame.repaint();
    }
}

class LabelButtonListener implements ActionListener {
    JLabel label = Gui.label;
    public void actionPerformed (ActionEvent event) {
        if (label.getText() == "That hurt") {
            label.setText("I'm a label");
        } else {
            label.setText("That hurt");
        }
    }
}

class MyDrawPanel extends JPanel {
    public void paintComponent (Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        int red = (int) (Math.random() * 256);
        int green = (int) (Math.random() * 256);
        int blue = (int) (Math.random() * 256);
        Color startColor = new Color(red, green, blue);

        red = (int) (Math.random() * 256);
        green = (int) (Math.random() * 256);
        blue = (int) (Math.random() * 256);
        Color endColor = new Color(red, green, blue);

        GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
        g2d.setPaint(gradient);
        g2d.fillOval(0, 0, this.getWidth(), this.getHeight());

    }
}
有一个用于绘制圆的面板类,然后将面板定位在框架的中心区域

标签位于框架的西部区域,两个按钮colorButton(位于南部)和labelButton(位于东部)应分别控制圆圈和标签。ColorButtonListener和LabelButtonListener两个类实现了ActionListener接口,分别注册到colorButton和labelButton。单击“颜色”按钮时,应使用随机颜色绘制一个圆圈,单击“标签”按钮时,应在文本“我是标签”和“那伤害”之间切换


现在,我遇到的问题是标签按钮。单击它时,它不仅会更改文本(如预期的那样),还会重新绘制圆。此按钮不应重新绘制圆。“颜色”按钮按预期工作

这是因为如果新文本与旧文本不同,则
setText()
方法在内部调用
repaint()
。这是因为如果新文本与旧文本不同,则
setText()
方法会在内部调用
repaint()
。因此,每当您单击该按钮时,也会导致颜色变化。

问题在于您无法控制重新绘制的时间。例如,不要每次调用
paintComponent
时都更改颜色(这是您无法控制的),而应仅在需要时更改颜色,并从
paintComponent
方法中进行引用

class MyDrawPanel extends JPanel {
    private Color startColor;
    private Color endColor;

    // And setters or some other way
    // to randomise the colors

    public void paintComponent (Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
        g2d.setPaint(gradient);
        g2d.fillOval(0, 0, this.getWidth(), this.getHeight());

    }
}

查看更多详细信息

问题在于您无法控制重新绘制的时间。例如,不要每次调用
paintComponent
时都更改颜色(这是您无法控制的),而应仅在需要时更改颜色,并从
paintComponent
方法中进行引用

class MyDrawPanel extends JPanel {
    private Color startColor;
    private Color endColor;

    // And setters or some other way
    // to randomise the colors

    public void paintComponent (Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        GradientPaint gradient = new GradientPaint(70, 70, startColor, 150, 150, endColor);
        g2d.setPaint(gradient);
        g2d.fillOval(0, 0, this.getWidth(), this.getHeight());

    }
}

查看更多详细信息

SetText-On并不能保证其他组件需要重新绘制(是的,标签需要重新绘制),真正的罪魁祸首很可能是标签大小的变化,这会导致容器层次结构的级联失效,这将导致其他容器重新绘制其中的内容…但您的语句较短;)SetText-On并不能保证其他组件将需要重新绘制(是的,标签将需要重新绘制),真正的罪魁祸首可能是标签大小的变化,这将导致容器层次结构的级联失效,这将导致其他容器重新绘制其中的内容……但您的语句较短;)