Java中的repaint()不';";“重新油漆”;马上?

Java中的repaint()不';";“重新油漆”;马上?,java,swing,repaint,paintcomponent,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();

我有这样一个代码:

// 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())
时,输出是正确的:

为什么?
paintComponent
方法可以工作,但有时它是盲的,所以我不想使用它。谁能给我一些建议?谢谢

了解您无法完全控制是否发生或何时发生 调用了paint(…)get,而repaint()调用只是 建议JVM进行绘制。如果传入的repaint()请求太多 它们会像你的一样堆积起来,然后它们会结合在一起

参考:

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

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

这意味着AWT/Swing可以通过合并快速连续请求的重绘来优化重绘。还有一种方法,允许您控制在完全填充重绘请求时允许AWT/Swing等待多长时间。不过,它可能仍然会合并请求,尤其是在循环中执行请求时

阅读这篇文章可能会有所帮助,它试图解释所涉及的各种概念

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

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

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

中阅读更多关于Swing和Threading的内容,正如其他答案所说:这是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
循环中会如何运行。

@Raghunandan:谢谢你的回答,但这不是我的问题。你是否按照mKorbel的建议立即尝试了绘画(…)。应该会有帮助。。我知道这不是答案。但我猜解决方案是线程。
SwingUtilities.invokeLater
对我不起作用。
repaint(长时间)
对我的系统没有任何作用,仍然需要等待0.5秒或类似的时间(我知道,因为我正在实现一个时钟)。整个Swing计时都是狗屎,至少在Ubuntu上是这样,而AMD360X不仅在一个内核上,而且在所有内核上都是零负载。
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);
    }
});