我看了很多,似乎没有人能给我答案。我有JPanel
我在其中添加/删除标签的地方;正在运行。问题是,每次我向其添加新标签时,我都必须revalidate()
,以便显示新标签。每当我revalidate()
时,我都会得到一个非常恼人的闪烁,我的所有标签都会闪现在我的窗口顶部一毫秒,然后回到他们正在做的事情。我添加标签后,唯一一次拨打revalidate()
;我不会改变绘画方法或只做任何事情
public void paintComponent(Graphics page)
{
super.paintComponent(page);
}
这样我的网页看起来不会很糟糕。我真的可以在这方面使用一些帮助。我使用JFrame
,Jlabel
和Jpanel
游戏进行了小行星游戏;它工作得很好,但是这个闪烁的组件“快速重影重影到面板顶部”实在是难以忍受,我知道这是revalidate()
方法。
答案 0 :(得分:2)
当我遇到使用Swing组件的问题时,结果证明是并发问题。由于你正在做一个游戏,这意味着你正在做动画,这可能就是这里的情况。
注意仅从AWT-EVENT thread
修改Swing组件。使用SwingUtilities.invokeLater
或使用javax.swing.Timer
制作动画。
答案 1 :(得分:2)
作为一个具体的例子,Asteroids
根本没有闪烁。原因如下:
它使用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);
}
}
更精细的游戏可能会命令游戏对象控制游戏对象如何相互重叠。但原则上它非常简单。