【发布时间】:2013-03-08 19:17:15
【问题描述】:
我有一个 JPanel,可以在其上执行自定义绘画,这可能需要 15 秒。
问题是,当我在绘制 JPanel 时单击菜单时,绘制是在菜单上完成的,并且选项不可见。 (看图片中扭曲的文字)
如果我在绘画完成后单击菜单,则不会出现意外行为,但是当我将鼠标指针移到不同的菜单上时,同样的事情又会发生。 例如,绘画完成后,如果我点击“应用程序”,不会出现副作用,但是当我将鼠标指针移到“帮助”上时,就会出现前面描述的行为。 如何避免这种情况?
我正在一个单独的线程中的 paintComponent() 方法之外执行绘画:
public class RandomIFSPanel extends JPanel {
RandomIFSPanelRenderer randomIFSPanelRenderer;
@Override
public void paintComponent(Graphics graphics) {
try {
randomIFSPanelRenderer.stop();
} catch (Exception e) {
}
randomIFSPanelRenderer = new RandomIFSPanelRenderer();
randomIFSPanelRenderer.start();
}
class RandomIFSPanelRenderer extends Thread {
@Override
public void run() {
for (int i = 0; i < numberOfPoints; i++) {
Graphics g=getGraphics();
g.setColor(Color.WHITE);
g.drawLine........
}
}
}
}
【问题讨论】:
-
你的线程很可能是这里的问题 - 如果你没有在 EDT 上完成所有绘画,那么你就是在自找麻烦/这样的怪癖。如果你使用
SwingUtilities.invokeLater(),问题还存在吗? -
Graphics g=getGraphics();是问题的另一部分。您应该考虑将整个绘画表面替换为BufferedImage(显示在JLabel)并将长期运行的工作转移到SwingWorker。 -
@berry120 如果我使用 SwingUtilities.invokeLater(randomIFSPanelRenderer) 而不是 randomIFSPanelRenderer.start(),则窗口在调整大小时变得无响应。
-
@AndrewThompson 整个绘画过程需要时间,我希望它能够实时完成,即我希望用户看到更新后的图像,因为像素被逐一计算和绘制。
-
“我想要实时完成” 我想要一匹会飞的小马,但这并不意味着我会得到一个。 Java GUI 体系结构无法支持“实时”方面。遵循我在第一条评论中概述的策略,使用
BufferedImage,每 100 次左右更新,在标签上调用repaint()。如果 JRE 不忙,将呈现这些更改,但如果它忙于进行其他 GUI 更新,则该调用可能会与其他重绘调用合并。您所做的一切都不会实现“实时”更新。