【问题标题】:Why does super.repaint() not call paint method?为什么 super.repaint() 不调用paint方法?
【发布时间】:2020-07-16 13:38:52
【问题描述】:

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

这是我的第一个问题,如果有什么遗漏,我很抱歉。

我的问题: 我想创建一个扩展 JPanel 的类,以便我可以在我的 JFrame 上绘制东西。我也希望它能够重新粉刷自己。到目前为止,run 方法有效,但 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 请求重新绘制,这意味着 EDT 将在它到达面板时重新绘制面板。因此,您的循环可能会在实际调用 paint 之前发生 20 次。
  • @matt 即使我省略了循环并在绘图中添加了一个我称之为重绘的构造函数,它也不起作用。
  • 你永远不应该在构造函数中调用 repaint。您需要创建一个完整的示例,因为您在帖子中遗漏了太多内容。例如,您是否将 jpanel 添加到 jframe 中?
  • 我现在没有将 JPanel 添加到 JFrame 中。这是一个新项目的开始,我想先进行重新粉刷。
  • 哦,那我就跳枪了。如果你不将你的 jpanel 添加到任何东西,那么为什么它会被重新粉刷呢?只要它没有被设置为可见,我怀疑paint会被调用。

标签: java swing jpanel paint runnable


【解决方案1】:

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

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

在您的“运行”方法中,您有一个循环,该循环将一条语句打印到终端“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 的次数。

【讨论】:

  • 我尝试离开 Sytem.out.println("test1") 但现在程序不打印任何东西。
  • @Quarkfelix 我添加了一个简单的示例,该示例会导致重新绘制 jpanel。由于您尚未将面板添加到任何内容,因此 swing 不会对其进行绘制。
  • 非常感谢。确实是缺少可见性。
  • @Quarkfelix 如果它解决了您的问题,最好将其标记为正确。有一张支票。
  • 如果它有助于解决问题,请accept the answer。这样做对所有人都有帮助,包括以后寻找解决方案的人。
猜你喜欢
  • 2011-05-07
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2014-10-28
  • 2011-04-09
  • 2019-09-01
  • 2012-08-25
  • 1970-01-01
相关资源
最近更新 更多