2016-09-29 2 views
-1

В настоящее время я делаю пошаговую игру с JLabel с оставшимся временем, несколькими другими лейблами для ответов на вопросы/ответы/команды и главной панелью с игровым полем.java.util.Timer && Свинг-неудачи

Первая проблема с этим кодом: класс GameTimer называется слишком часто, I.E. он не вызывается каждую секунду, а около 5-10 раз в секунду. (Оператор печати, который выводит «Timer:» + timeElapsed, печатает каждое число до 80 (таймер: 1, таймер: 2 и т. Д.) В течение примерно 10 секунд. В качестве побочной заметки время для вопроса никогда не превышает 15 секунд. Если циферблат while не останавливается до того, как он пройдет, это может произойти только иногда. Я предполагаю, что это ошибка, связанная с использованием .Timer, а не в моем коде, но я не слишком хорошо знаком с внутренней работой класса

Вторая проблема: каждый цикл вызывается в бесконечном цикле, так как в нем печатаются «Достигнутые вопросы. Количество вопросов:» + questions.size() и продолжается до: каждый цикл бесконечно. не думал, что windowOpened() можно было бы вызвать несколько раз, и я также использовал windowActivated() с теми же результатами.

Окончательный выпуск: t ime-метка обновляется только после истечения времениElapsed превышает question.getTime, что означает, что метка будет содержать только отрицательное число. Цикл while должен обнаруживать, что timeElapsed больше и останавливается, но это не так.

Я смущен этим, любая помощь очень ценится.

Немного истории проекта: перед внедрением windowListener класс просто ждал за 30 секунд до выполнения цикла for: each, который не работал, потому что окно будет серым экраном (разгружено) до тех пор, пока таймер не будет закончен, и тогда он будет загружаться нормально, но GameTimer запускается сразу после 30-секундного таймера. Затем я попытался использовать Thread, чтобы обновлять себя каждую секунду, но с аналогичными проблемами была связана с предыдущей попыткой.

Существуют и другие классы, кроме этого. Эти 2 являются те, я считаю, что ошибки внутри:

Код экрана игры:

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); 
    } 
} 

Top код панели:

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); 
    } 
} 
+0

В вашем коде не должно быть даже этого цикла while - для этого используется таймер, это то, что заменяет таймер. –

+0

Почему не используется [Swing Timer] (https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)? –

+0

Я просто собирался сказать, что @ PM77-1 сказал выше (и я не могу проголосовать за его комментарий, поскольку у меня нет голосов). Swing GUI должен использовать javax.swing.Timer или Swing Timers, а не java .util.Timer. В противном случае у вас возникнут проблемы с потоками. –

ответ

1

Вы начинаете новый объект Timer с каждым итерация цикла while, и поэтому это ускоряет ваше поле TimeElapsed с дополнительной скоростью, каждый раз, когда в цикле создается новый экземпляр Timer. Решение состоит в том, чтобы не делать этого, использовать только один таймер или останавливать таймер перед созданием нового ..., но, сказав это, у вас есть другие серьезные проблемы в вашем коде, в том числе:

  • Это приложение Swing, и вы не должны использовать java.util.Timers, а скорее javax.swing.Timers или «Swing Timers». Причиной этого является то, что Swing Timers хорошо работают с потоком событий Swing, а таймеры Utility - нет, и это может привести к появлению прерывистых и дьявольски трудных для отладки ошибок.
  • Нельзя использовать цикл while, поскольку вы рискуете блокировать поток событий Swing (или EDT для «Event Dispatch Thread»), делая ваш графический интерфейс замороженным. Вместо этого используйте свой таймер, а также конструкцию State Machine, чтобы предотвратить необходимость цикла while.

Если вам нужна дополнительная помощь, пожалуйста, ответьте на комментарии выше и помогите нам с вашим minimal example program, который мы можем запускать и изменять самостоятельно.Мы не хотим видеть всю вашу программу, а также не хотим ссылок, а самую маленькую программу, которая показывает нам вашу проблему.

Смежные вопросы