JLabel's Set Location inside 移动不流畅
JLabel's Set Location inside for not moving smoothly
我正在为我正在做的一些测试使用一个小精灵的标签,但我想在每次按键时将精灵移动 10 个像素。现在,我可以做到了,但现在我正试图让它平滑地移动 10 个像素,所以我尝试了下一个代码:
for(int i = 0; i < 100; i++){
x++;
container.setLocation(x, y);
System.out.println(x);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
现在的问题是,精灵只在 for 循环结束时移动,但控制台显示每次迭代都会改变 X 值。有 thoughts/help 吗?
谢谢!
如果您不创建新线程,则用户界面运行与其方法在同一个线程上。
因此你的 for-cycle 在一些动作之后被触发,并且线程在它结束之前不能做任何其他事情。
解决方案:创建您自己的 class,将 JLabel 或整个表单作为构造函数中的参数传递,实现线程化并 运行 将其作为新线程。
如果您想在 Swing 中做一些接近动画的事情,我建议您看看 Timing Framework。它可以帮助你,这取决于你的一般需要。
如果您希望其他精灵与您的精灵同步移动,您可以创建一个 TimerTask
并使用 scheduleAtFixedRate()。然后,您的 TimerTask
将负责移动所有精灵并重新绘制移动中的所有内容,例如背景中的 JPanel
和精灵。
要使您的代码片段正常工作,您必须在设置位置后重新绘制背景和精灵,但我建议不要使用这种方法,因为它很容易导致代码设计不当,从而导致您创建一个上帝 Class 什么都做。
如果计算需要一点时间,TimerTask
方法也应该更精确,因为它试图在 2 次调用之间有相同的时间,其中睡眠线程的方法很容易导致不同的延迟,如果计算早晚完成。
我建议您看一下如何使用 Swing Timer class, instead of for loop. You can find various tutorials about how to use Swing Timer. Here, to briefly explain, you are blocking EDT(Event Dispatch Thread) 为 JComponent 设置动画,它操作 Java 的图形端。每当您想在动画中制作连续流畅的动画时,请确保您永远不会阻塞 EDT。
编辑:这里是Swing Timer的用法演示Class:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class AnimationTrial extends JFrame {
private final int DELAY = 10;
private Timer timer;
private int x, y;
private JLabel label;
public static void main(String[] args) {
EventQueue.invokeLater( new Runnable () {
@Override
public void run() {
new AnimationTrial();
}
});
}
public AnimationTrial()
{
setSize(500, 500);
x = 50;
y = 50;
label = new JLabel("They see me movin' they hatin'!");
timer = new Timer( DELAY, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0) {
x++;
label.setLocation(x, y);
}
});
timer.start();
getContentPane().add(label);
pack();
setVisible (true);
}
}
我正在为我正在做的一些测试使用一个小精灵的标签,但我想在每次按键时将精灵移动 10 个像素。现在,我可以做到了,但现在我正试图让它平滑地移动 10 个像素,所以我尝试了下一个代码:
for(int i = 0; i < 100; i++){
x++;
container.setLocation(x, y);
System.out.println(x);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
现在的问题是,精灵只在 for 循环结束时移动,但控制台显示每次迭代都会改变 X 值。有 thoughts/help 吗? 谢谢!
如果您不创建新线程,则用户界面运行与其方法在同一个线程上。
因此你的 for-cycle 在一些动作之后被触发,并且线程在它结束之前不能做任何其他事情。
解决方案:创建您自己的 class,将 JLabel 或整个表单作为构造函数中的参数传递,实现线程化并 运行 将其作为新线程。
如果您想在 Swing 中做一些接近动画的事情,我建议您看看 Timing Framework。它可以帮助你,这取决于你的一般需要。
如果您希望其他精灵与您的精灵同步移动,您可以创建一个 TimerTask
并使用 scheduleAtFixedRate()。然后,您的 TimerTask
将负责移动所有精灵并重新绘制移动中的所有内容,例如背景中的 JPanel
和精灵。
要使您的代码片段正常工作,您必须在设置位置后重新绘制背景和精灵,但我建议不要使用这种方法,因为它很容易导致代码设计不当,从而导致您创建一个上帝 Class 什么都做。
如果计算需要一点时间,TimerTask
方法也应该更精确,因为它试图在 2 次调用之间有相同的时间,其中睡眠线程的方法很容易导致不同的延迟,如果计算早晚完成。
我建议您看一下如何使用 Swing Timer class, instead of for loop. You can find various tutorials about how to use Swing Timer. Here, to briefly explain, you are blocking EDT(Event Dispatch Thread) 为 JComponent 设置动画,它操作 Java 的图形端。每当您想在动画中制作连续流畅的动画时,请确保您永远不会阻塞 EDT。
编辑:这里是Swing Timer的用法演示Class:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class AnimationTrial extends JFrame {
private final int DELAY = 10;
private Timer timer;
private int x, y;
private JLabel label;
public static void main(String[] args) {
EventQueue.invokeLater( new Runnable () {
@Override
public void run() {
new AnimationTrial();
}
});
}
public AnimationTrial()
{
setSize(500, 500);
x = 50;
y = 50;
label = new JLabel("They see me movin' they hatin'!");
timer = new Timer( DELAY, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent arg0) {
x++;
label.setLocation(x, y);
}
});
timer.start();
getContentPane().add(label);
pack();
setVisible (true);
}
}