当前位置: 首页 > 面试题库 >

Java中的repaint()不会立即“重画”吗?

黄向明
2023-03-14
问题内容

我有这样的代码:

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


问题答案:

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

如果此组件是轻量级组件,则此方法将导致尽快调用此组件的paint方法。否则,此方法将导致 尽快 调用此组件的update方法。

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

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

要使面板在每次迭代时都重新粉刷,您必须等待粉刷发生,然后继续循环。这意味着您需要在处理线程(循环)和AWT /
Swing线程之间进行一些同步。粗略地讲,例如wait(),如果循环对象的最后一次调用repaint()notifyAll()在面板paintComponent()方法结尾处的调用之后尚未重绘,则可以在循环末尾的面板对象上。但是,这可能难以正确实现,因此,仅在确实需要“实时”重绘组件时才应这样做。作为替代方案,paintImmediately(...)可以使用,但是您必须在事件分配线程中进行所有处理,如下所示:

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

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



 类似资料:
  • 我想问一下,为什么在执行事件时,我的状态没有改变。我已经搜索到需要在构造函数中绑定函数,但是状态仍然没有更新。 下面是我的代码:

  • 问题内容: 我想问为什么在执行onclick事件时状态没有变化。我已经搜索了一段时间,我需要在构造函数中绑定onclick函数,但状态仍未更新。这是我的代码: 问题答案: 这个回调真的很混乱。只需使用async await代替:

  • 问题内容: 我想问一下为什么在执行onclick事件时状态没有变化。我已经搜索了一段时间,我需要在构造函数中绑定onclick函数,但状态仍未更新。这是我的代码: 问题答案: 幸运的是, setState进行了回调。这是我们获取更新状态的地方。考虑这个例子。 因此,当回调触发时,this.state是更新后的状态。你可以在回调中获取突变/更新的数据。

  • 问题内容: 在一个简短的方法中,我使用setVisible(false)隐藏了一个JFrame。然后,截屏并使用setVisible(true)还原JFrame。 在再次显示之后,窗口应该显示与以前不同的图片(可以说是截图的一部分)。 问题是,在调用setVisible(true)之后,将窗口与旧内容一起闪烁一秒钟,然后再调用paintComponent并绘制更新的状态。 我可能会以丑陋的方式解决

  • 在试图制作一个非常简单的子弹地狱游戏来学习java时,我遇到了一个障碍: repaint()没有调用油漆组件()。 这是整个程序,目前只需将我每秒创建50次的图像绘制到JFrame上的JPanel上。 在使用断点和println方法进行了一些调试之后,我可以确认正在读取正确的图像,gameTimerAction中的计时器每秒被调用50次,并且repaint()根本没有调用paintComponen

  • 我有一些动画,我试图转换为约束。它背后的想法是当出现错误时登录提示会反弹。 我的方法是,视图控制器上的所有内容都在bounceView中,而bounceView本身也在主视图中。 BounceView使用居中约束和前导空间约束绑定到主视图。为了使布局在设计时明确无误,还有一个前导空间和顶部空间约束。不过,这些只是占位符,在运行时被等高/宽约束替换。 没有其他约束与主视图相关联。 现在,一些细节…