【问题标题】:repaint() JPanel if previous repaint() completerepaint() JPanel 如果之前的 repaint() 完成
【发布时间】:2015-10-21 16:11:23
【问题描述】:

我在课堂collection 中有一个循环,其中repaint() JPanel 不断

    while(loop) {
        imageicon = (ImageIcon) ois.readObject();
        image = imageicon.getImage();
        cjpanel.tempimage = image;
        cjpanel.repaint();
        Thread.sleep(100);
    }

cjpanel 扩展了JPanel,我已经覆盖了paintComponent() 并且我正在使用Double buffering

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
tempimage.getScaledInstance(dim.width, dim.height, Image.SCALE_FAST);
bufferGraphics.clearRect(0,0,dim.width,dim.width);
bufferGraphics.drawImage(tempimage,0,0,dim.width,dim.height, null);
g.drawImage(offscreen,0,0,this);
}

我的问题是 repaint 总是在 while 循环后面两帧。即如果image 4while 循环中,那么paintComponent() 正在绘制`图像2。

那么在之前的repaint 完成之前,我怎样才能加速repaint 或停止新的repaint

更新

当我从 ObjectInputStream 更改图像的大小时,它工作正常。我认为这与图像大小有关..

【问题讨论】:

  • 您的while 循环位于何处?使用image 的代码在哪里?此外,您正在调用tempimage.getScaledInstance,但您忽略了返回的缩放图像。此外,在我看来,保持相同的bufferGraphics 对象“打开”在理论上应该可行,但它的代码味道很差。最后,JPanel 自己做双缓冲,所以你可能应该将你的图像传递给一个 drawImage 方法,该方法接受四个 int 参数,而不是自己缩放它。
  • @VGR 请查看我更新的问题。我正在使用cjpanel 显示图像
  • "我正在使用双缓冲" Swing 已经是双缓冲了,你不需要做任何事情。
  • @user1803551 是的 Swing 已经是双缓冲了..

标签: java swing paintcomponent repaint


【解决方案1】:
  1. 您不应在 while 循环中重新读取图像。一次读取图像并将它们存储在一个变量中,可能是一个集合,例如 ArrayList。
  2. 根据您使用它们的方式将它们存储为图像或图标。当您可以将图像存储为图像时,无需在图标上调用 getImage()。
  3. 不要使用 while 循环,而应使用 Swing 计时器,以免违反 Swing 线程规则。
  4. 您在寻求调试帮助,本质上是“为什么这段代码没有按预期工作?”帮助,因此,如果一般性建议没有帮助,您真的必须认真考虑创建和发布最短的代码,以便我们能够编译、运行和帮助识别您的问题,minimal example program(请查看链接)。否则,除了提供一般性建议之外,我们将无法提供很好的帮助,就像我在上面所做的那样。而且我同意我的要求不会是一件容易或快速的事情,因为这需要你付出相当多的努力,但如果你仍然陷入困境并需要解决这个问题,那将是值得的努力.由您决定,完全取决于您的需要。

【讨论】:

  • tempimage in paintComponent 是图像,所以我必须 getImage()
  • @reenleedr:您在寻求调试帮助,本质上是“为什么这段代码没有按预期工作?”帮助,因此,如果一般建议没有帮助,您确实必须创建并发布最短的代码,以便我们能够编译、运行和帮助识别您的问题。否则,除了提供一般性建议之外,我们将无法提供很好的帮助,就像我在上面所做的那样。
  • 先生,我正在寻找最短的示例,但我的应用程序太复杂了..
  • @reenleedr:我同意我的要求不会是一件容易或快速的事情,因为这需要您付出相当多的努力,但是如果您仍然卡住并需要解决这个问题,这将是值得的努力。由您决定,完全取决于您的需要。无论如何,祝你好运!
  • @reenleedr:有关使用 Swing Timer 和图像 ArrayList 的示例,请查看我在this recent program 中的代码答案。在其中,我创建了一个 ArrayList<Icon> 来保存图像尺寸不断增加的 ImageIcon。然后,当鼠标悬停在按钮上时,会触发一个摆动计时器,它会连续交换图标,显示一个不断增长的图像。当鼠标离开按钮时会发生相反的情况。
【解决方案2】:

重绘管理器可以折叠对repaint 的顺序调用,这样如果您为每张图像绘制一帧,某些图像可能不会显示。您可以使用paintImmediately 强制重绘:

立即绘制此组件中的指定区域及其与该区域重叠的所有后代。

很少需要调用这个方法。在大多数情况下,调用 repaint 会更有效,这会延迟实际的绘制,并且可以将多余的请求合并到单个绘制调用中。如果在调度当前事件时需要更新显示,此方法很有用。

至于

当我从 ObjectInputStream 更改图像的大小时,它工作正常。

它可能会影响重绘管理器计算如何/哪个重绘调用折叠。

我建议你试试这个方法,看看它是否有效,虽然它更难实现(仔细阅读 API)。

感谢this post 刷新我的记忆。

【讨论】:

  • @HovercraftFullOfEels 谢谢。我认为如果这是解决方案,那么这个问题应该被标记为我链接的那个的副本。
  • 是在repaint() 之后调用paintImmediately 还是应该像OBJ.paintImmediately(rectangle r) 一样手动调用它
  • @reenleedr 后者(自己没有测试)。
  • paintImmediately 是否调用 paintComponent??
  • @reenleedr 我认为它调用了paint。见this。必须查看源代码才能确定。
猜你喜欢
  • 2014-08-14
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 2023-03-06
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
相关资源
最近更新 更多