JLabel的设置位置在里面,因为移动不顺利



我正在为一个小精灵使用标签进行一些测试,但我想每次按键移动精灵 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 值都会发生变化。有什么想法/帮助吗?谢谢!

我建议你看看如何使用Swing Timer class而不是for循环来制作JComponent的动画。您可以找到有关如何使用摆动计时器的各种教程。在这里,为了简要解释一下,你正在阻止EDT(事件调度线程),它操作Java的图形端。每当您想要在动画中保持恒定和流畅的流动时,请确保永远不会阻塞 EDT

编辑:这是摆动计时器类的使用演示:

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

如果不创建新的 Thread,用户界面将与其方法在同一线程上运行。

因此,您的 for 循环在某些操作后被触发,线程在结束之前无法执行任何其他操作。

解决方案:创建自己的类,在构造函数中将 JLabel 或整个表单作为参数传递,实现线程并将其作为新线程运行。

如果你想在Swing中做一些接近动画的事情,我建议你看看计时框架。它可以根据您的一般需求为您提供帮助。

如果你想让

其他精灵与你的精灵同步移动,你可以创建一个TimerTask并使用 scheduleAtFixedRate()。然后,您的TimerTask将负责移动所有精灵并重新绘制移动过程中的所有内容,例如背景中的JPanel和精灵。

为了使您的代码片段正常工作,您必须在设置位置后添加背景和精灵的重绘,但我建议不要使用这种方法,因为它很容易导致设计不良的代码,您可以在其中创建一个可以执行所有操作的 God 类。

如果计算需要一点时间,TimerTask方法也应该更精确,因为它尝试在 2 个调用之间具有相同的时间,如果计算提前或延迟完成,则使用休眠线程的方法很容易导致不同的延迟。

相关内容

最新更新