JLabel设置位置内部不能顺利移动

时间:2015-04-15 09:36:53

标签: java swing for-loop 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值都在变化。有什么想法/帮助吗? 谢谢!

4 个答案:

答案 0 :(得分:3)

我建议你看看如何使用Swing Timer class动画JComponent,而不是for循环。您可以找到有关how to use Swing Timer的各种教程。在这里,简要解释一下,您正在阻止EDT(Event Dispatch Thread)操作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);
    }

}

答案 1 :(得分:2)

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

因此,你的for-cycle在一些动作之后被触发,并且线程不能做任何其他事情直到它结束。

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

答案 2 :(得分:0)

如果你想在Swing中做一些接近动画的事情,我建议你看看Timing Framework。它可以帮助您,具体取决于您的一般需求。

答案 3 :(得分:0)

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

为了使您的代码片段工作,您必须在设置位置后添加背景和精灵的重绘,但我会建议不要使用该方法,因为它很容易导致设计错误的代码,您可以创建一个完成所有操作的God Class

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