本文介绍了Java中的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())时,输出是正确的:

But when I change panel.repaint() to panel.paintComponent(panel.getGraphics()), the out is right:

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

Why? paintComponent method works, but sometimes it's blind, so I don't want to use it. Anybody can give me some suggestions? Thanks!

推荐答案

如果您阅读,您会注意到它指出(强调我的意思):

If you read the documentation of repaint carefully, you will notice that it states that (emphasis mine):

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

This means that AWT/Swing is allowed to optimize repainting by merging repaints that are requested in a rapid succession. There is also a repaint(long time) method, which allows you to control how long AWT/Swing is allowed to wait with fullfilling your repaint request. It might still merge requests though, especially if you do them in a loop.

阅读"AWT和Swing中的绘画"一文可能会有所帮助试图解释所涉及的各种概念.

It might be helpful to read the article "Painting in AWT and Swing", which tries to explain the various concepts involved.

要使面板在每次迭代时都重新粉刷,您必须等待粉刷发生,然后继续循环.这意味着您需要在处理线程(循环)和AWT/Swing线程之间进行一些同步.大致来说,您可以例如 wait() 在循环末尾的面板对象上,如果自上次调用repaint()并调用在面板的paintComponent()方法末尾.但是,这可能很难正确实现,因此,仅在确实需要实时"重绘组件时才应这样做.或者, paintImmediately(...) 可以使用,但是您必须在事件分配线程中进行所有处理,如下所示:

To get the panel repainted for every iteration, you would have to wait for a paint to happen and then proceed with your loop. This means you need some synchronization between your processing thread (the loop) and the AWT/Swing thread. As a rough idea, you could for example wait() on the panel object at the end of your loop if it has not been repainted since the last call to repaint() and call notifyAll() at the end of your panel's paintComponent() method. However, this can be tricky to implement right, so you should only do this if you really need "real-time" redrawing of your component. As an alternative, paintImmediately(...) could be used, but you would have to do all your processing in the event dispatching thread, like this:

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

请注意,这将在循环运行时停止任何事件处理(包括鼠标和键盘输入)的处理.您可以在"Swing中的并发性"

Note that this will stop any event processing including mouse and keyboard input from being processed while your loop is running. You can read more about Swing and Threading in "Concurrency in Swing"

这篇关于Java中的repaint()不会“重新绘制";立即地?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 15:35