【发布时间】:2016-09-29 19:48:55
【问题描述】:
目前,我正在制作一个回合制游戏,其中包含一个带有剩余时间的 JLabel、其他几个用于问题/答案/团队得分的标签,以及一个带有游戏板的主面板。
此代码的第一个问题:GameTimer 类被过于频繁地调用,即它不是每秒都被调用,而是每秒大约 5-10 次。 (输出“Timer:” + timeElapsed 的打印语句在大约 10 秒内打印每个数字,最多可达 80 左右(Timer: 1、Timer: 2 等)。作为旁注,问题的时间永远不会超过 15秒。while 循环不应该在它失控之前停止吗?这个问题只是偶尔发生。我认为这是一个 util.Timer 相关的错误,不在我的代码中,但我不太熟悉类的内部工作.
第二个问题:for:each 循环在无限循环中被调用,因为它会打印“Reached Questions. Number of questions:” + questions.size() 并无限期地继续 for:each 循环。没想到windowOpened()可以被多次调用,我也用了windowActivated(),结果一样。
最后一个问题:时间标签只有在timeElapsed超过question.getTime后才会更新,这意味着标签中只会有一个负数。 while 循环应该检测到 timeElapsed 更大,然后停止,但它没有。
我对所有这些都感到困惑,非常感谢任何帮助。
项目的一点历史:在实现 windowListener 之前,该类在执行 for:each 循环之前只等待了 30 秒,这不起作用,因为在计时器完成之前窗口将是灰屏(卸载),并且然后它会正常加载,但 GameTimer 在 30 秒计时器后立即启动。然后我尝试使用线程每秒更新一次,但这与之前的尝试有类似的问题。
除此之外还有其他类。这两个是我认为错误在其中的:
游戏画面代码:
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import java.util.*;
import java.awt.event.*;
@SuppressWarnings("deprecation")
public class GameScreen implements WindowListener{
private int team1Score = 0;
private int team2Score = 0;
private ArrayList<Question> questions;
private Question cQuestion;
private boolean start = false;
private boolean timesUp = false;
private boolean isCorrect = false;
private java.util.Timer timer = new java.util.Timer();
private int timeElapsed = 0;
private boolean isTeam1 = true;
private String correctAnswer = "";
private String inputAnswer = "";
private int numIncorrect = 0;
private TopPanel topPanel = new TopPanel();
public GameScreen(ArrayList<Question> questions) {
JFrame gameFrame = new JFrame("Cavazos Math Game");
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int)screenSize.getWidth();
int height = (int)screenSize.getHeight();
gameFrame.setSize(width, height);
gameFrame.setResizable(false);
gameFrame.setLocationRelativeTo(null);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
topPanel.setSize(width, 200);
this.questions = questions;
BorderLayout layout = new BorderLayout();
gameFrame.setLayout(layout);
System.out.println("Reached Image Loading");
try {
BufferedImage fieldImage = ImageIO.read(new File("field2.png"));
GamePanel gamePanel = new GamePanel(fieldImage);
gamePanel.setSize(width, height - 200);
gameFrame.add(gamePanel, BorderLayout.CENTER);
}
catch(Exception e) {System.out.println("RUH ROH");}
System.out.println("Reached Layout Loading");
gameFrame.add(topPanel, BorderLayout.NORTH);
gameFrame.setVisible(true);
gameFrame.addKeyListener(topPanel);
gameFrame.addWindowListener(this);
}
public void windowDeactivated(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowOpened(WindowEvent e) {
System.out.println("Reached Questions. Number of question: " + questions.size());
for(Question question : questions) {
timeElapsed = 0;
cQuestion = question;
timesUp = false;
topPanel.setQuestion(question.getQuestionString());
setTimer(question.getTime());
correctAnswer = question.getAnswer();
System.out.println(question.getTime() + "");
while((timeElapsed < question.getTime()) && !isCorrect && (numIncorrect <= 4)) {
if(!topPanel.getInput().equals("nothing")) { //has an answer been submitted?
inputAnswer = topPanel.getInput();
if(!inputAnswer.equals(correctAnswer)) { //is it the wrong answer
numIncorrect++;
topPanel.setAnswer("");
}
else {
numIncorrect = 0;
isCorrect = true;
if(isTeam1) {
team1Score += question.getPoints();
}
else {
team2Score += question.getPoints();
}
}
}
else {
}
topPanel.setTimer(cQuestion.getTime() - timeElapsed);
}
isTeam1 = !isTeam1;
}
}
class GameTimer extends TimerTask {
public void run() {
System.out.println("Timer: " + timeElapsed);
timeElapsed++;
topPanel.setTimer(cQuestion.getTime() - timeElapsed);
}
}
public void setTimer(int seconds) {
System.out.println("Timer has started");
timer = new java.util.Timer();
timer.schedule(new GameTimer(), 0, 1000);
}
}
顶部面板代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TopPanel extends JPanel implements KeyListener {
JLabel questionLabel = new JLabel("Test Question");
JTextField answerLabel = new JTextField("Answer label");
JTextField timer = new JTextField("Timer Label");
JTextField team1 = new JTextField("Team 1: 0");
JTextField team2 = new JTextField("Team 2: 0");
JPanel teamScores = new JPanel();
//timer.setEditable(false);
//team1.setEditable(false);
//team2.setEditable(false);
//answerLabel.setEditable(false);
String inputString = "";
boolean doneInputting = false;
GridLayout scoresLayout = new GridLayout(2,1);
GridLayout topLayout = new GridLayout(1,4);
public TopPanel() {
teamScores.setLayout(scoresLayout);
teamScores.add(team1);
teamScores.add(team2);
this.setLayout(topLayout);
this.setSize(getWidth(), 100);
this.add(questionLabel);
this.add(answerLabel);
this.add(timer);
this.add(teamScores);
Font topFont = new Font("Sans Serif", Font.PLAIN, 32);
this.setFont(topFont);
}
public void setQuestion(String question) {
questionLabel.setText(question);
}
public void setAnswer(String answer) {
answerLabel.setText(answer);
}
public void setTimer(int time) {
timer.setText(time + "");
}
public void setTeam1Score(int score) {
team1.setText(score + "");
}
public void addTeam1Score(int score) {
team1.setText(score + "");
}
public void setTeam2Score(int score) {
team2.setText(score + "");
}
public String getInput() {
if(doneInputting) {
return inputString;
}
return "nothing";
}
public String getCurrentInput() {
return inputString;
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_9) {
inputString += "9";
}
else if(e.getKeyCode() == KeyEvent.VK_8) {
inputString += "8";
}
else if(e.getKeyCode() == KeyEvent.VK_7) {
inputString += "7";
}
else if(e.getKeyCode() == KeyEvent.VK_6) {
inputString += "6";
}
else if(e.getKeyCode() == KeyEvent.VK_5) {
inputString += "5";
}
else if(e.getKeyCode() == KeyEvent.VK_4) {
inputString += "4";
}
else if(e.getKeyCode() == KeyEvent.VK_3) {
inputString += "3";
}
else if(e.getKeyCode() == KeyEvent.VK_2) {
inputString += "2";
}
else if(e.getKeyCode() == KeyEvent.VK_1) {
inputString += "1";
}
else if(e.getKeyCode() == KeyEvent.VK_0) {
inputString += "0";
}
else if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
inputString = inputString.substring(0, inputString.length()-1);
}
else if(e.getKeyCode() == KeyEvent.VK_T) {
inputString += "TRUE";
}
else if(e.getKeyCode() == KeyEvent.VK_F) {
inputString += "FALSE";
}
else if(e.getKeyCode() == KeyEvent.VK_P) {
inputString += "π";
}
else if(e.getKeyCode() == KeyEvent.VK_S) {
inputString += "√";
}
else if(e.getKeyCode() == KeyEvent.VK_ENTER) {
doneInputting = true;
}
else if(e.getKeyCode() == KeyEvent.VK_SLASH) {
inputString += "/";
}
setAnswer(inputString);
}
}
【问题讨论】:
-
你的代码甚至不应该有那个 while 循环——这就是 Timer 的用途,这就是 Timer 所取代的。
-
为什么不使用Swing Timer?
-
我只是想说上面@PM77-1 所说的话(我不能投票赞成他的评论,因为我没有投票权)——Swing GUI 应该使用 javax.swing。计时器或摆动计时器,而不是 java.util.Timer。否则你会遇到一堆线程问题。
-
此外,如果您创建并发布 minimal reproducible example,您将获得更好的答案,您将在其中将代码压缩成仍然可以编译和运行的最小位,没有外部依赖项(例如需要链接到数据库或图像),没有与您的问题无关的额外代码,但仍演示您的问题。我们不希望看到您的整个程序,当然也不希望您发布代码链接,但显示问题的小型可运行程序会大有帮助。
-
另外,代码不应该有
@SuppressWarnings("deprecation")。相反,请避免使用已弃用的代码。
标签: java multithreading swing timer windowlistener