当我在单个 JFrame 中有多个 JPanel 对象时,repaint() 如何工作?

How does repaint() work when I have multiple JPanel objects in a single JFrame?

我读到过,当 JPanel 对象(或扩展 JPanel 的 class 的任何实例)是 JFrame 的一部分时,每次 JVM认为 JFrame 需要刷新,调用 JPanel 实例的 paintComponent() 方法。

但是当我有两个这样的对象时会发生什么,它们是两个 不同 classes 的实例? 运行 我最后提供的代码,我发现两个 paintComponent() 方法都被调用,当我最小化、更改大小或按 colourButton 时。

但是,当我按下 labelButton 时,不是 的情况。它只调用 MyDrawPanel paintComponent()。为什么会这样?

提前致谢!

class GUI {

    JFrame frame;
    JLabel label;

    void go() {
        JButton labelButton = new JButton("Click me to change that (<-) text");
        labelButton.addActionListener(new LabelListener());
        JButton colourButton = new JButton("Click me to change the colour");
        colourButton.addActionListener(new ColourListener());

        label = new JLabel("Don't change me!");

        frame = new JFrame();
        frame.setSize(600, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        MyDrawPanel Q = new MyDrawPanel();
        DrawPanel P = new DrawPanel();

        frame.getContentPane().add(BorderLayout.CENTER, Q);
        frame.getContentPane().add(BorderLayout.EAST, labelButton);
        frame.getContentPane().add(BorderLayout.WEST, label);
        frame.getContentPane().add(BorderLayout.SOUTH, colourButton);
        frame.getContentPane().add(BorderLayout.NORTH, P);

    }

    class LabelListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event){
            label.setText("You've changed me!");
        }
    }

    class ColourListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event){
            MyDrawPanel.red = (int) (Math.random() * 255);
            MyDrawPanel.green = (int) (Math.random() * 255);
            MyDrawPanel.blue = (int) (Math.random() * 255);
            frame.repaint(); 
        }
    }
}

class MyDrawPanel extends JPanel {

    static int red = (int) (Math.random() * 255);
    static int green = (int) (Math.random() * 255);
    static int blue = (int) (Math.random() * 255);

    @Override
    public void paintComponent(Graphics g){
        Color randomColour = new Color(red, green, blue);

        g.setColor(randomColour);

        g.fillOval(70, 70, 75, 75);

        System.out.println("Q");
    }
}

class DrawPanel extends JPanel {

    @Override
    public void paintComponent(Graphics g){

        System.out.println("P");

    }
}
frame.repaint(); 

这会告诉框架重新绘制自身及其所有子项。所以框架上的所有组件都重新粉刷了。

label.setText("You've changed me!");

setText() 方法将调用标签上的 revalidate()repaint()repaint() 告诉标签重新绘制自身及其所有子项。

如果任何组件的大小发生变化,revalidate() 将调用布局管理器。在这种情况下,标签看起来会变大。这意味着添加到中心的面板(您的 DrawPanel)会变小,因此也需要重新绘制。

NORTH/SOUTH中的组件不受标签大小变化的影响,因此不会重新绘制。

所以 Swing 只会重新绘制任何必要的东西,以尽量减少绘制。