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