Java中的repaint()并没有重新绘制"立即?

时间:2012-11-19 11:57:55

标签: java swing repaint paintcomponent

我有这样的代码:

// In MyPanel.java
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    // Draw something
    mypanel_count++;
}

// In Test.java
public void testLargeData()
{
    while (notDone)
    {
        panel.repaint();
        // do huge work
        test_count++;
        System.out.println("Test_count: " + test_count + ", MyPanel_count: " + mypanel_count);
    }
}

// Output !!!
Test_count: 752, MyPanel_count: 23
Test_count: 753, MyPanel_count: 23
Test_count: 754, MyPanel_count: 23
Test_count: 755, MyPanel_count: 24

但是当我将panel.repaint()更改为panel.paintComponent(panel.getGraphics())时,输出是正确的:

Test_count: 752, MyPanel_count: 752
Test_count: 753, MyPanel_count: 753
Test_count: 754, MyPanel_count: 754
Test_count: 755, MyPanel_count: 755

为什么呢? paintComponent方法有效,但有时它是盲目的,所以我不想使用它。有人可以给我一些建议吗?谢谢!

3 个答案:

答案 0 :(得分:11)

如果您仔细阅读repaint的文档,您会注意到它(强调我的):

  

如果此组件是轻量级组件,则此方法会导致   尽快调用此组件的绘制方法。除此以外,   此方法会立即调用此组件的更新方法   可能

这意味着允许AWT / Swing通过合并快速连续请求的重绘来优化重绘。还有一个repaint(long time)方法,它允许您控制AWT / Swing在完全填充重绘请求时等待的时间。它可能仍会合并请求,特别是如果你在循环中执行它们。

阅读文章"Painting in AWT and Swing"可能会有所帮助,该文章试图解释所涉及的各种概念。

为了让每次迭代都重新绘制面板,你必须等待绘制,然后继续你的循环。这意味着您需要在处理线程(循环)和AWT / Swing线程之间进行一些同步。作为一个粗略的想法,如果自上次调用repaint()以来没有重新绘制,并且最后调用wait(),那么您可以在循环结束时的面板对象上notifyAll()你小组的paintComponent()方法。但是,实现这一点可能很棘手,所以只有在真正需要“实时”重新绘制组件时才应该这样做。作为替代方案,可以使用paintImmediately(...),但您必须在事件调度线程中执行所有处理,如下所示:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        while(notDone) {
            // Do your processing
            panel.paintImmediately(...);
        }
    }
});

请注意,这将停止任何事件处理,包括在循环运行时处理鼠标和键盘输入。您可以在"Concurrency in Swing"

中阅读有关Swing和Threading的更多信息

答案 1 :(得分:1)

正如其他答案所说:这是AWT何时调用paint()的问题。

如果你做一些需要绘制/布局组件信息的工作,那么将这项工作放到一个等待绘画完成的工作线程中也有帮助。

在你的情况下会是这样的:

panel.repaint();

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        // do huge work
        test_count++;
        System.out.println("Test_count: " + test_count 
             + ", MyPanel_count: " + mypanel_count);
    }
});

虽然我不确定它在while循环中的表现如何。

答案 2 :(得分:0)

  

了解您无法完全控制if或when   paint(...)得到了调用,而repaint()调用只是一个   建议JVM绘画。如果有太多repaint()请求进来   并且它们会像你的一样堆叠起来,然后它们将被合并

参考: https://stackoverflow.com/a/13256847/1423083