6

我有这样的代码:

// 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方法有效,但有时它是盲目的,所以我不想使用它。有人可以给我一些建议吗?谢谢!

4

3 回答 3

13

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

如果此组件是轻量级组件,则此方法会尽快调用此组件的绘制方法。否则,此方法会尽快调用此组件的更新方法。

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

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

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

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

请注意,这将在循环运行时停止处理任何事件处理,包括鼠标和键盘输入。您可以在“Swing 中的并发”中阅读更多关于 Swing 和线程的信息

于 2012-11-19T12:21:42.293 回答
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循环中会如何表现。

于 2013-10-22T15:00:56.917 回答
0

了解您无法完全控制是否或何时调用 paint(...),并且 repaint() 调用只是对 JVM 绘制的建议。如果有太多的 repaint() 请求进入并且它们像你的那样堆积起来,那么它们将被合并

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

于 2012-11-19T12:18:26.180 回答