java swing计时器在调试时工作正常,但在运行时却不能

java swing计时器在调试时工作正常,但在运行时却不能,java,swing,timer,frame-rate,Java,Swing,Timer,Frame Rate,我已经试着做了几个小时了,现在我不知所措。我想以每秒30帧的速度运行我的游戏。回转计时器延迟设置为1000/30。即使我把速度降低到1000或2000,也不会改变任何事情。在一步一步调试中,一切都按预期进行。下次计时器刷新时将调用“updateALL()”方法。但是在运行时,updateAll从未被调用,甚至一次也没有(sysout从未打印)。我删减了下面的代码,只是为了显示关键部分。它应该编译 这是我的侦听器类: public class Observer implements ActionL

我已经试着做了几个小时了,现在我不知所措。我想以每秒30帧的速度运行我的游戏。回转计时器延迟设置为1000/30。即使我把速度降低到1000或2000,也不会改变任何事情。在一步一步调试中,一切都按预期进行。下次计时器刷新时将调用“updateALL()”方法。但是在运行时,updateAll从未被调用,甚至一次也没有(sysout从未打印)。我删减了下面的代码,只是为了显示关键部分。它应该编译

这是我的侦听器类:

public class Observer implements ActionListener {

    private int timerFrame;
    private int fps;
    private boolean frameComplete;

    public Observer() {
        this.frameComplete = true;
        this.timerFrame = 0;
    }

    @Override
    public void actionPerformed(ActionEvent aEvent) {
            nextTimerFrame();
    }

    public void frameCompleted() {
        frameComplete = true;
        System.out.println("Fcompleted");
    }

    public int getTimerFrame() {
        return timerFrame;
    }

    public void setFps(int fps) {
        this.fps = fps;
    }

    private void nextTimerFrame() {
        System.out.println(timerFrame);
        if(frameComplete) {
            if(timerFrame == fps) {
                timerFrame = 1;
            } else {
                ++timerFrame;
            }
            frameComplete = false;
        }
    } 
}
下面是我的GameClock类中的代码:

public class GameClock {
    private Timer timer;
    private Observer observer;
    private GameEngine gameEngine;
    private View view;
    private boolean paused;
    private boolean quit;
    private int clockFrame;

    public GameClock() {}
    public GameClock(GameEngine gameEngine) {
        this.gameEngine = gameEngine;
        this.paused = false;
        this.quit = false;
        setupTimer();
        this.clockFrame = 0;
        run();
    }

    public void updateAll() {
            readInputs();
            updateGameEngine();
            updateCanvas2D();
            updateCanvas3D();
            clockFrame = clockFrame == 30? 1:clockFrame+1;  
            observer.frameCompleted(); // puts frameComplete at "true" in Observer
            System.out.println("update" + clockFrame);
    }

    public void run() {
        while(!quit) {
            int timerFrame = observer.getRefreshFrame();
            if(!paused && (clockFrame < timerFrame || (clockFrame == 30 && timerFrame == 1))) {
                updateAll();
                //System.out.println("update");
            }
        }
    }

    private void setupTimer() {
        int fps = Config.getFps();
        int delay = Math.round(1000/fps); 
        observer.setFps(fps);
        this.timer = new Timer(delay, observer);
        timer.start();
    }   
    private void readInputs() {

    }

    private void updateGameEngine() {
    }

    private void updateCanvas2D() {
    }

    private void updateCanvas3D() {
    }
}
公共类游戏时钟{
私人定时器;
私人观察员;
私人游戏引擎;
私人视野;
私有布尔运算暂停;
私人布尔退出;
专用int时钟帧;
公共游戏时钟(){}
公共游戏时钟(游戏引擎游戏引擎){
this.gameEngine=gameEngine;
this.pause=false;
this.quit=false;
设置计时器();
这个.clockFrame=0;
run();
}
public void updateAll(){
readInputs();
updateGameEngine();
updateCanvas2D();
updateCanvas3D();
时钟帧=时钟帧==30?1:时钟帧+1;
observer.frameCompleted();//在observer中将frameComplete设置为“true”
System.out.println(“更新”+时钟帧);
}
公开募捐{
而(!退出){
int timerFrame=observer.getRefreshFrame();
如果(!暂停&&(时钟帧
更新:

一些奇怪的观察:

如果我在while循环的“if”语句中放入2个sysout,它们就不会打印。这不提供打印输出:

public void run() {
    while(!quit) {
        int clockFrame = observer.getRefreshFrame();
        //System.out.println("clock" + clockFrame);
        //System.out.println("frame" + refreshFrame);
        if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
            System.out.println("clock" + clockFrame);
            System.out.println("frame" + refreshFrame);
            updateAll();
            //System.out.println("update");
        }
    }
}
public void run(){
而(!退出){
int clockFrame=observer.getRefreshFrame();
//系统输出打印项次(“时钟”+时钟帧);
//System.out.println(“帧”+刷新帧);
如果(!暂停&&(refreshFrame
如果我将前面的sysout放在注释中,并将//从“If”语句之外的2中删除,如下所示:

public void run() {
    while(!quit) {
        int clockFrame = observer.getRefreshFrame();
        System.out.println("clock" + clockFrame);
        System.out.println("frame" + refreshFrame);
        if(!paused && (refreshFrame < clockFrame || (refreshFrame == 30 && clockFrame == 1))) {
            //System.out.println("clock" + clockFrame);
            //System.out.println("frame" + refreshFrame);
            updateAll();
            //System.out.println("update");
        }
    }
}
public void run(){
而(!退出){
int clockFrame=observer.getRefreshFrame();
系统输出打印项次(“时钟”+时钟帧);
System.out.println(“帧”+刷新帧);
如果(!暂停&&(refreshFrame
我看到refreshFrame总是随着clockFrame的增加而增加。这毫无意义。如果updateAll从未被调用,则不会递增

更新2-一些解释:

  • swing计时器需要一个侦听器,并在它滴答作响时生成actionPerformed()事件。这就是为什么我需要一个观察者
  • 我不能直接让计时器调用“updateAll()”,因为计时器在它自己的线程上。如果我这样做,计时器可能会在上一次更新尚未完全完成时调用“updateAll()”
  • 它“应该”工作的方式:while保持循环,不做任何事情,直到它看到计时器滴答作响(时钟帧低于计时器帧)。然后它将更新all()。除非上一个updateAll()已完全完成(在updateAll结束时frameComplete设置为true),否则无法增加timerFrame。更新完成后,下一个计时器勾号将增加timerFrame,从而生成新的更新
  • 在理论上和逐步调试中,它可以工作,但不能在运行时工作

以下是一个文件(将整个代码复制粘贴到
GameClock.java
),演示如何使用swing
计时器以30fps的速度更新swing
视图:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

public class GameClock {

    private final Observer observer;
    private final View view;

    public GameClock() {
        view = new View();
        observer = new Observer(view);
        setupTimer();
    }

    private void setupTimer() {
        int fps = 30;
        int delay = Math.round(1000/fps);
        observer.setFps(fps);
        Timer timer = new Timer(delay, observer);
        timer.setInitialDelay(0);
        timer.start();
    }

    public static void main(String[] args) {
        new GameClock();
    }
}

class View {

    private JLabel counter;

    View(){
        createAndShowGui();
    }

    void createAndShowGui(){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationRelativeTo(null);
        counter = new JLabel("0", SwingConstants.CENTER);
        f.add(counter);
        f.pack();
        f.setVisible(true);
    }

    void setCounter(int i){
        counter.setText(String.valueOf(i));
    }
}

class Observer implements ActionListener {

    private int timerFrame;
    private int fps;
    private final boolean paused;
    private final View view;

    public Observer(View view) {
        this.view = view;
        paused = false;
        timerFrame = 0;
    }

    @Override
    public void actionPerformed(ActionEvent aEvent) {
        if (! paused) {
            updateAll();
        }
    }

    public int getTimerFrame() {
        return timerFrame;
    }

    public void setFps(int fps) {
        this.fps = fps;
    }

    private void nextTimerFrame() {
        timerFrame = timerFrame >= fps ?    0 : timerFrame + 1;
    }

    public void updateAll() {
        nextTimerFrame();
        view.setCounter(timerFrame);
    }
}

很难确定,但我猜您是
而循环
正在阻止事件调度线程,其中包括阻止触发
计时器
。我有点想知道,虽然您需要
while循环
计时器
,但它对我来说没有多大意义。考虑提供一个演示“你如何使用你的班级”,我用更多的观察来更新我的文章。计时器将递增,系统将定期打印nextRefreshFrame()内的sysout。如果我理解正确,计时器有自己的线程。我发现代码很混乱。在两个类中都有一个“refreshFrame”变量,但在一个类中也称之为clockFrame。你有一个循环和一个计时器。通常你只有一个定时器,它代替了循环的逻辑。然后在计时器中更改类中变量的状态。我不知道为什么会有Observer class.tks,我更新了我的帖子,给出了更多的解释,并更改了变量名,以减少混淆。1。请按建议邮寄mre。它不仅使帮助更容易,而且是一个强大的调试工具。很多情况下,在准备一个时,您可能会发现问题所在。2.我在
GameClock
3中没有看到
observer
初始化。计时器可能会调用“更新”