重新验证JPanel时闪烁

时间:2013-02-16 10:28:17

标签: java swing jframe jpanel jlabel

我看了很多,似乎没有人能给我答案。我有JPanel我在其中添加/删除标签的地方;正在运行。问题是,每次我向其添加新标签时,我都必须revalidate(),以便显示新标签。每当我revalidate()时,我都会得到一个非常恼人的闪烁,我的所有标签都会闪现在我的窗口顶部一毫秒,然后回到他们正在做的事情。我添加标签后,唯一一次拨打revalidate();我不会改变绘画方法或只做任何事情

public void paintComponent(Graphics page)
{
    super.paintComponent(page);
}

这样我的网页看起来不会很糟糕。我真的可以在这方面使用一些帮助。我使用JFrameJlabelJpanel游戏进行了小行星游戏;它工作得很好,但是这个闪烁的组件“快速重影重影到面板顶部”实在是难以忍受,我知道这是revalidate()方法。

4 个答案:

答案 0 :(得分:2)

当我遇到使用Swing组件的问题时,结果证明是并发问题。由于你正在做一个游戏,这意味着你正在做动画,这可能就是这里的情况。

注意仅从AWT-EVENT thread修改Swing组件。使用SwingUtilities.invokeLater或使用javax.swing.Timer制作动画。

答案 1 :(得分:2)

作为一个具体的例子,Asteroids根本没有闪烁。原因如下:

  • 它在event dispatch thread

  • 上运行
  • 它使用JPanel,默认为双缓冲。

  • 使用javax.swing.Timer调整动画速度,在actionPerformed()更新游戏模型。

  • 它会覆盖paintComponent(),但可以安全地省略super.paintComponent(),因为动作侦听器会重新绘制整个面板。

  • 听众呼叫paintImmediately()以避免任何潜在的延迟;替换repaint()以查看您的平台上是否存在任何差异。

附录:如此counter-example所示,revalidate()不会导致闪烁。 替换标签,更新标签的图标,如图here所示。

答案 2 :(得分:2)

您是否考虑过重复使用它们 - 即在不需要时使用setVisible(false)

不确定添加和删除标签是否是实现游戏所需内容的最佳方式。 我个人很想自己管理绘图。

答案 3 :(得分:2)

使用标签(或通常是GUI组件)来快速表示动画,动态创建/移动的对象是不实际的。就像用汽车从起居室开车到厨房一样。

Swing组件具有许多不错的功能,例如他们可以确定他们需要的空间,布局管理员可以使用它来自动放置它们。不幸的是,对于游戏来说,你既不需要所有好东西,也不想支付它所涉及的处理开销。摇摆多平台功能使事情变得更加复杂,这要求每个组件都有一个对等组件(对等体处理将组件呈现为活动外观)。

要解决此问题,您不要将单个游戏对象表示为挥杆组件。相反,您使用单个swing组件(通常为JPanel)作为画布来绘制游戏对象。您只需定期为该JPanel调用repaint()(例如每秒30或60次)。当然,您将覆盖JPanel上的paintComponent()以使用您自己的代码绘制所有游戏对象。

编辑:概述您如何进行自己的渲染

您需要决定如何整理与游戏相关的对象。一个非常简单的骨架可能看起来像这样(省略了getters / setters):

public class GameObject {
    public int x;
    public int y;
    public Image image;
}

在实践中,此类将具有其他成员(如控制对象移动方式的行为,以及动画的某些状态/计数器)。对于每种可能的行为(如船,小行星和子弹),它也可能是抽象的具体子类。 GameObject的所有实例都在某种集合中进行管理,我假设你使用了List。

实现paintComponent时,它只是循环遍历列表并渲染每个对象的图像:

public void paintComponent(Graphics g) {
    List<GameObject> list = ... // however you obtain it in your game
    for (GameObject gobject : list) {
        g.drawImage(gobject.image, gobject.x, gobject.y, (ImageObserver) null);
    }
}

更精细的游戏可能会命令游戏对象控制游戏对象如何相互重叠。但原则上它非常简单。