首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java Swing移动卡顿

Java Swing移动卡顿
EN

Stack Overflow用户
提问于 2015-04-18 16:54:08
回答 1查看 771关注 0票数 0

在Java Swing中移动块时遇到卡顿。

下面的代码将显示该问题。运行时,我希望盒子移动得顺畅,没有任何卡顿。在Swing中有什么方法可以做到这一点吗?或者我应该直接转到JavaFX?

MovementStutter.java

代码语言:javascript
复制
package movementstutter;

import javax.swing.JFrame;

public class MovementStutter {

public static void main(String[] args) {
    JFrame win = new JFrame("Stutter Demo");
    win.getContentPane().add(new GamePanel());
    win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    win.setResizable(false);
    win.pack();
    win.setVisible(true);
}

}

GamePanel.java

代码语言:javascript
复制
package movementstutter;

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements Runnable {

private boolean running;
private Thread thread;
private double x;
private double y;
private double movementFactor;

public GamePanel() {
    setPreferredSize(new Dimension(640, 480));
    setFocusable(true);
    grabFocus();
    movementFactor = 1;
    running = true;
}

@Override
public void addNotify() {
    super.addNotify();
    if (thread == null) {
        thread = new Thread(this);
        thread.start();
    }
}

@Override
public void run() {
    long time = System.currentTimeMillis();
    while (running) {
        update();
        repaint();
        long sleep = 16 - (System.currentTimeMillis() - time);
        time += 16;
        if (sleep < 0) {
            sleep = 16;
        }
        try {
            Thread.sleep(sleep);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

private void update() {
    if (x < 0) {
        movementFactor = 1;
    } else if (x > 608) {
        movementFactor = -1;
    }
    x += movementFactor * 200 * 0.016;
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.fillRect((int) x, (int) y, 32, 32);
}

}
EN

回答 1

Stack Overflow用户

发布于 2015-04-18 17:26:45

您正在不是事件分派线程的线程中更新swing组件。你不该那样。要执行定时操作,可以使用javax.swing.Timer

例如,不实现Runnable,而是让您的面板实现ActionListener,删除与线程相关的内容,并添加一个操作侦听器:

代码语言:javascript
复制
public void actionPerformed(ActionEvent e) {
    update();
    repaint();
}

然后,在面板的构造函数中,可以创建一个Timerjavax.swing.Timer确保在事件分派循环中执行该操作。它还简化了时间管理:

代码语言:javascript
复制
public GamePanel() {
    setPreferredSize(new Dimension(640, 480));
    setFocusable(true);
    grabFocus();
    movementFactor = 1;
    running = true;
    new Timer(16,this).start();
}

如果您需要在任何时候停止计时器,那么您应该将其分配给一个字段,例如

代码语言:javascript
复制
Timer blockTimer = new Timer(16,this);

然后你就这么做了

代码语言:javascript
复制
blockTimer.start();

在你的构造函数中,你可以有一个按钮,它的动作包括

代码语言:javascript
复制
blockTimer.stop();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29715049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档