为什么 super.repaint() 不调用 paint 方法?

Why does super.repaint() not call paint method?

解决方案:我需要将 JPanel 添加到 JFrame 中。 paint 方法的调用与 JFrame 的可见性绑定。 感谢@matt

这是我的第一个问题,如有遗漏,我深表歉意。

我的问题: 我想创建一个扩展 JPanel 的 class,以便我可以在我的 JFrame 上绘制内容。我也希望它能够重新粉刷自己。到目前为止,运行 方法有效,但 super.repaint() 无效。正在打印“test1”而“test2”没有。

提前致谢:)

public class Main {
    public static GUI gui;
    
    public static void main(String[] args) {
        gui = new GUI();
    }
}
public class GUI extends JFrame{
    public Draw draw;
    public Thread drawT;
    
    public GUI() {
        draw = new Draw();
        drawT = new Thread(draw);
        drawT.start();
    }
}
public class Draw extends JPanel implements Runnable{
    
    @Override
    public void run() {
        while (true) {
            System.out.println("test1");
            super.repaint();
        }   
    }   
    
    @Override
    public void paint(Graphics graphics) {
        System.out.println("test2");
        Graphics2D g = (Graphics2D)graphics;
        
    }
}

repaint 安排要绘制的组件。 如果组件不可见,则不会调用绘制。

一种简化的查看方式。 Swing/AWT 有 EventDispatchThread,它持续 运行s,处理事件和绘制组件。当您调用“repaint”时,它会告诉 swing 为您的组件安排一个绘制事件。它不叫油漆。当 EDT 找到它时,它会绘制您的组件。

在您的 'run' 方法中,您有一个循环将语句打印到终端“test1”,然后调用 repaint(),然后重复。这里最慢的是 System.out.println.

你有一个非常快的循环淹没 AWT 重绘请求,但该循环 运行 比 EDT 循环 运行 绘制事件快。因此,在 EDT 实际执行一次绘制之前,您可能打印 test1 并调用 repaint 100 次。我怀疑如果你仔细观察,test2 被埋在你的输出中的某个地方。

import java.awt.*;

public class MainS{
    int paints = 0;
    int tags = 0;
    public void runGui(){
        JFrame frame = new JFrame("testing");
        JPanel panel = new JPanel(){
            @Override
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                paints++;
            }
        };
        
        frame.add(panel, BorderLayout.CENTER);
        JLabel label = new JLabel("times painted ...");
        frame.add(label, BorderLayout.NORTH);
        
        frame.setSize(200, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Timer t = new Timer( 1000, evt->{
            label.setText(paints + "/" + tags);
            paints = 0;
            tags = 0;
        });
        t.start();
        
        new Thread( ()->{
            while(true){
                tags++;
                panel.repaint();
            }
        }).start();

    }
    public static void main(String[] args){
        EventQueue.invokeLater( new MainS()::runGui );
    }

}

这是一个简单的示例,其中组件实际被重新绘制。它会在帧的顶部显示paintComponent被调用的次数和repaint被调用的次数。