Thread.sleep()停止我的油漆?

时间:2014-02-08 23:06:15

标签: java multithreading swing graphics jframe

我正在制作一个程序,试图让卡片在屏幕上移动,就好像你真的从桌面上画了一样。以下是动画的代码:

public void move(int x, int y) {
    int curX = this.x; //the entire class extends rectangle
    int curY = this.y;

    // animate the movement to place
    for (int i = curX; i > x; i--) {
        this.x = i;
    }

    this.x = x;
    this.y = y;
}

此矩形对象位于jframe内部的面板内。为了重新粉刷小组,我有这个:

public void run() {
    while (Core.isRunning()) {
        gamePanel.repaint(); //panel in which my rectangle object is in

        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这是一个线程,每50毫秒重新绘制一次游戏面板。

现在,我意识到这可能不是做这种事情的最好方法。如果有更好的方法来做这整个重绘的事情,请通知我!

但是,我遇到的问题是,当我为我的矩形调用move()命令时,它会通过线程,但图像不会更新直到结束,所以它只是从点a跳到最后的位置。

为什么会这样?任何人都可以批评/改进我的代码吗?谢谢!

2 个答案:

答案 0 :(得分:3)

问题是您在Event Dispatch Thread中调用了Thread.sleep(),导致GUI无法响应。为避免这种情况,您可能需要使用Swing Timer代替:

   Timer timer = new Timer(50, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if(!stop) {
                gamePanel.repaint();
            } else {
                ((Timer)e.getSource()).stop();
            }
        }
    });
    timer.setRepeats(true);
    timer.setDelay(50);
    timer.start();

其中stop是一个布尔标志,表示动画必须停止。

答案 1 :(得分:-1)

最有可能的是,方法for中的move()循环运行速度太快,您看不到任何转换。解决此问题的最简单方法是在move()方法中在循环内添加睡眠,例如:

public void move(int x, int y) {
    int curX = this.x; //the entire class extends rectangle
    int curY = this.y;

    // animate the movement to place
    for (int i = curX; i > x; i--) {
        this.x = i;
        Thread.sleep(20); // Just experiment with other sleep amounts
    }
    this.x = x;
    this.y = y;
}

关于重绘逻辑,在每个循环中让一个单独的线程重绘所有内容通常是低效的,主要是因为你可能正在重新绘制实际没有变化的东西。通常更新只更新变化的东西会更有效。

在一个复杂的情况下,几个形状相互重叠,你需要确定哪些变化和什么不变,因为如果某些事物没有移动但是被一些形状重叠,你需要更新重叠的形状以确保正确绘制。有一些软化的algortihms可以解决这个问题,但是如果你的场景没有很多形状,那么当事情发生变化时重新绘制所有内容可能会更简单。