2013-02-16 63 views
1

我已经看了四周,似乎没有人对我有任何答案。我有一个JPanel,当它运行时,我可以在其中添加/删除标签。问题是,每次我给它添加一个新标签时,我都必须revalidate(),这样新标签才会显示出来。每一次,我都会产生一个非常烦人的闪烁,我的所有标签都会在我的窗口顶部闪烁一毫秒,然后回到他们正在做的事情上。我唯一一次打电话revalidate()是在我添加一个标签之后;我不改变涂装方法或任何东西只有闪烁同时重新验证JPanel

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

这样我的网页不会看起来不好。我真的可以在这方面使用一些帮助。我做了一个小行星游戏,使用JFrame,JlabelJpanel游戏;它工作的很好,但这种闪烁和组件“鬼鬼祟祟地重影到面板上方”是无法忍受的,我知道这是revalidate()方法。

+0

有关信息,我有一个代表船舶,子弹和小行星的标签,我将它们添加到我的面板并将它们移除,因为它们被用于拍摄或耗尽生命。使用add(component);并删除(对手);然后我添加我重新验证。 – Elton 2013-02-16 10:30:56

回答

2

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

Swing组件带有很多很好的功能,例如,他们可以确定他们需要的空间,布局经理可以使用它自动将它们很好地放置。不幸的是,对于一款游戏,你不需要所有的好东西,也不需要支付与之相关的处理开销。通过摆动多平台功能使问题变得更加复杂,其要求每个组件具有对等组件(对等组件处理将组件呈现为活动外观)。

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

编辑:概述你怎么做你自己的渲染

您需要决定如何组织你的游戏相关的对象。一个很简单的骨架看起来是这样的(省略getter/setter方法):

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); 
    } 
} 

更复杂的游戏,可以责令gameobjects获得的游戏对象如何相互重叠的控制。但原则上它非常简单。

+0

唯一的问题,我不知道如何解决,因为即时通讯NOB是每个东西,即子弹,小行星和船,有很多事情我不知道如何表示为图形。 – Elton 2013-02-16 19:03:12

+0

@Elton我添加了一些简要说明,你如何创建自己的游戏对象并渲染它们 – Durandal 2013-02-18 13:40:23

2

当我在摆动Swing组件时遇到问题,结果是并发问题。既然你正在做一个游戏,这意味着你正在做动画,它可能就是这种情况。

只能从AWT-EVENT thread修改Swing组件。请使用SwingUtilities.invokeLater或使用javax.swing.Timer做动画。

2

作为具体示例,Asteroids根本不闪烁。原因如下:

  • 它运行在event dispatch thread上。

  • 它使用JPanel,默认情况下是双缓冲。

  • 它使用javax.swing.Timer来加速动画,更新游戏的模型actionPerformed()

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

  • 听众呼叫paintImmediately()以避免任何潜在的延迟;请替换repaint()以查看您的平台是否有任何区别。

附录:如在本counter-example所示,revalidate()不会引起闪烁。而不是替代标签,更新标签的图标,如here所示。

2

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

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

+0

我想我会尝试这个,我仍然是业余编码器,所以这对我来说似乎最简单,谢谢你的反馈人。 – Elton 2013-02-16 19:00:10