使用 Swing 动画计时 [英] Timing with Swing animation

查看:24
本文介绍了使用 Swing 动画计时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Swing 和动画角色方面遇到了一些问题,我有一个带有键侦听器的 JFrame,当用户按下时,它会在此处调用我的 JPanel 方法

i have some problems with Swing and animate a character, I Have a JFrame with key listener and when the user hit down,it calls my JPanel method here

for(int i=1;i<4;i++)
{           
    pY+=16;
    g.drawImage(perso,pX,pY,pX+50,pY+50,0+50*i,0,50+50*i,50,this 
    this.repaint();                 
}

这个动画我的角色但是速度太快了,我们可以看到一个东西,我该怎么做才能查看动画?

This animate my character but so fast that we can see a thing,how do i can do to view the animation?

推荐答案

Jonas 已经给出了答案(使用 Swing 计时器),但它可能有助于解释为什么看不到动画以及为什么计时器是这个问题的最佳解决方案.

The answer is already given by Jonas (use a Swing timer), but it might be useful to explain why you are not seeing the animation, and why the timer is the best solution for this problem.

为什么我看不到不同的重绘

当您调用 JComponent#repaint 时,JComponent 不会重新绘制.相反,重新绘制某个组件的异步请求被安排在 EDT 上.如果您调用许多 repaint 调用,Swing 可能会决定将这些请求分组并只重新绘制组件一次.

When you call JComponent#repaint the JComponent is not repainted. Instead, an asynchronous request to repaint a certain component is scheduled on the EDT. If you invoke many repaint calls, Swing might decide to group those requests and repaint the component just once.

我没有立即在 Oracle 文档中找到对此的官方参考(Swing 绘画文章 好像没有提到).我发现这一点的唯一地方是这篇文章的注释,但我很确定这是在某处记录的.

I did not immediately found an official reference for this in the Oracle documentation (the Swing painting article does not seem to mention it). The only place where I found this was in a note in this article, but I am pretty certain this is documented somewhere.

为什么使用 Timer 是最好的解决方案

Why is using a Timer the best solution

对于一个动画,你基本上想说:

For an animation, you basically want to say:

我的角色应该在 y 毫秒内移动 x 个像素

my character should move x pixels in y milliseconds

最好,您希望在屏幕上有流畅的动画,因此您需要经常重新绘制.如果你记住这一点

And preferably, you want to have a smooth animation on screen so you need to repaint rather frequently. If you keep in mind that

  • 与 Swing 组件的所有交互都应在 EDT(事件调度线程,请参阅 Swing 中的并发 文章了解更多信息)
  • 您永远不应该阻止 EDT,因为这会冻结您的 UI,这意味着您不能在 EDT 中等待"直到重绘完成或重绘永远不会发生
  • 重绘请求可以分组,因此调用重绘 x 次并不能保证你的 paint 方法也被调用 x
  • All interaction with the Swing components should happen on the EDT (Event Dispatch Thread, see the Concurrency in Swing article for more info)
  • You should never block the EDT as this will freeze your UI, meaning you cannot 'wait' in the EDT until a repaint is done or the repaint will never happen
  • Repaint requests can be grouped, so calling repaint x times does not guarantee you that your paint method is called x times as well

克服此限制的解决方案是使用 Timer.使用相同的示例(在屏幕上移动角色),您可以使用 Timer 更新角色的位置并安排重绘.由于 Timer 代码是在 EDT 上触发的,因此您不会违反 Swing 线程规则.

The solution to overcome this limitations is to use a Timer. With the same example (moving a character on screen), you can use a Timer to update the position of the character and schedule a repaint. Since the Timer code is triggered on the EDT, you do not violate the Swing threading rules.

在组件的 paintComponent 方法中,然后在当前位置绘制字符.这可能是上一个位置 + 1",或上一个位置 +2"(或...),具体取决于在前一个 paint<之间触发了 Timer 的次数/code> 调用和当前的 paint 调用.这可确保您的角色移动速度与系统无关.只有动画的平滑度取决于您的系统(例如:有多少重绘请求被分组).

In the paintComponent method of your component, you then paint the character at the current location. This might be the 'previous location + 1', or the 'previous location +2' (or ...) depending on how many times the Timer has been triggered between the previous paint call and the current paint call. This ensures the speed at which your character moves is system-independent. Only the smoothness of the animation will depend on your system (as in: how many repaint requests get grouped).

Swing Timer 教程 乔纳斯已经链接到的包含更多信息.

The Swing Timer tutorial to which Jonas already linked contains more information.

这篇关于使用 Swing 动画计时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆