从Java中的另一个类调用重绘?

时间:2009-04-21 13:59:08

标签: java multithreading swing animation timer

我可能做错了,所以请你好。 我正在开发一个Java游戏,我正处于测试角色移动/动画的阶段。

“人”可以在网格上向左和向下移动。 绘制网格的类是gamePanel类。 这些按钮位于gameControlPanel类中。

我有一个按钮,可以在网格上生成一个人。 然后我有一个按钮可以左右移动这个人。

按下向上移动按钮时,它会调用person类中的move up方法。 (目前,我一次只测试一个“人”。) 在该方法中是以下代码......

int move = 10;
while(move!=0)
{
    setTopLeftPoint(new Point((int)getTopLeftPoint().getX(),
                              (int)getTopLeftPoint().getY() - 3));

    try
    {
        Thread.sleep(300);
    } catch (InterruptedException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
    move-=1;
}

问题是我似乎无法从Person类中调用gamePanel类的重绘方法。 为了解决这个问题,我在gamePanel类中创建了一个计时器,它每20ms重新绘制一次。

当我产生人物后按下向上按钮时,按钮保持按下直到while循环完成循环,然后人物的圆圈表示显示在上面的网格方格中。

我会尽力回答有关此事的任何问题。

4 个答案:

答案 0 :(得分:2)

repaint()不会立即重新绘制GUI。相反,它向AWT线程发布消息,告诉它在下一个方便的机会画画。当它有机会时,它会重新绘制你的应用程序。但是,如果在事件处理程序中执行此操作,则AWT线程已经忙,您需要退出处理程序以将控制权交还给AWT处理程序。

作为一般经验法则, 想要在AWT线程(包括事件处理程序)中进行任何长时间运行的计算,因为这会阻止应用程序响应其他事件直到你的计算完成。对于用户来说,这通常会显示为您所描述的卡住按钮。要解决此问题,请使用SwingWorker,它可以在单独的线程上进行计算。

最后,需要注意的事情(但不一定要改变)是定时器和睡眠并不能保证什么时候它们会被唤醒。相反,他们保证在经过一段时间之前不会唤醒,但理论上可以无限期地睡觉。此外,并非所有机器都具有1 ms定时器分辨率。特别是,在许多Windows机器上,定时器只有55毫秒的分辨率,所以一个20毫秒的定时器可能会产生奇怪的结果。

答案 1 :(得分:1)

如果您想以特定间隔重新粉饰,javax.swing.Timer可能适合您。在repaint的特定情况下,您可以从非EDT线程调用它,但是您可能会遇到困难,因为您现在处理多个线程。

答案 2 :(得分:0)

我没有太多制作游戏的经验,但拥有控制所有动画的循环是游戏编程的一个基本方面。大多数简单的2D游戏只有1个循环来渲染它的大部分动画。

根据我的经验,渲染大量内容的好方法是在一个地方拥有游戏中所有实体的集合,然后循环遍历此集合,将Graphics对象传递给每个实体。

这将允许每个实体将自己绘制到图形对象上。虽然这只是一种方法。

synchronized ( entities ) {
    for ( Entity e : entities ) {
        e.draw( g );
        e.doAction();
    }
}

答案 3 :(得分:0)

按下按钮是否由GUI的事件派发线程处理?

如果是这种情况,那么GUI上的重绘方法将不会触发,直到事件发送线程结束(即当按钮被释放并且它突然出现循环时)。我最近遇到了这个问题,我建议的最好的解决方案是使用移动算法的类可以线程化,并在检测到按键时触发线程。这允许事件派发线程完成,因此允许gui重绘。

有关线程的详细信息,请参阅Starting a thread