0

我在这里检查了其他线程,但没有找到解决方案。

1) JFrame 是 setVisible(true)。

2)这是什么意思:“我想知道您的问题是否是并发问题,您正在 Swing 事件线程上执行长时间运行的过程,这会阻止您的标签更新其文本。” 我在别的地方读到了。

3)我没有多次初始化包含标签的JPanel。

编辑: 4) updateTurn 从包含TrackingPanel(ie gamePanel) 的 JPanel 中调用。我调用该方法changeTurns();,这是代码:

public void changeTurns() {
    if(turnPlayer == playerX)
        turnPlayer = playerO;
    else
        turnPlayer = playerX;

    trackingPanel.updateTurn();
}   

以下是完整的相关代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TrackingPanel extends JPanel{

    /*TURN STUFF*/
    private JPanel turnPanel; //turns panel to keep track of whose turn it is
    private JLabel turnLabel;
    private String turn;

    /*OTHER*/
    private GamePanel gamePanel;


    public TrackingPanel( GamePanel gamePan ) {

        setLayout( new GridLayout(1,4) );
        setBorder(BorderFactory.createMatteBorder(2,2,4,2,Color.BLACK));

        gamePanel = gamePan;

        /*THIS PANEL DISPLAYS THE TEXT*/
        turnPanel = new JPanel( new GridLayout(2,1) );
        turn = gamePanel.getPlayerTurn().getLetter();
        turnLabel = new JLabel("      Player " + turn + "'s turn");
        add( turnPanel);

    }//end constructor

    /*THIS IS WHERE THINGS GO WRONG*/
    public void updateTurn() {

        turn = gamePanel.getPlayerTurn().getLetter();
        turnLabel.setText( "      Player" + turn + "'s turn" );
        System.out.println(turn);
    }
}

在被叫到之前updateTurn()turnLabel说“轮到 PlayerX”。之后,它应该说“轮到PlayerO了”。通过打印turn(我得到字符串'O',而不是'X'),我知道正在显示的内容(“PlayerX's turn”)不是应该显示的内容(“PlayerO's turn”)。

在此先感谢您的聪明人!

编辑。尝试提供 SSCCE 但不知道如何包含图像文件。对不起!

4

3 回答 3

7

尝试使用这个:

 private void setText(final JLabel label, final String text){
    label.setText(text);
    label.paintImmediately(label.getVisibleRect());
 }
于 2013-08-23T23:52:43.100 回答
3

我会确保您的方法 updateTurn() 使用 SwingUtilities.invokeLater(new Runnable()) 方法在 Swing 的线程中调用其代码。

于 2013-07-08T21:57:05.013 回答
2

我已更改您的代码,使其不需要图像,现在添加了 turnLabel。它仍然太大,但它运行并显示了一些行为:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;

public class GameFrame extends JFrame {

   public static void main(String[] args) {

      JFrame gameFrame = new JFrame("MyGame");

      gameFrame.setResizable(false);
      gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      gameFrame.add(new GamePanel());
      gameFrame.pack();
      gameFrame.setVisible(true);

   }
}

class GamePanel extends JPanel implements ActionListener {

   private BoardPanel boardPanel; // comprised of 9 mini panels
   /* RELEVANT */
   private static TrackingPanel trackingPanel; // keeps track of score, turn,
                                               // and stuff
   private static Player playerX, playerO, turnPlayer;
   private ArrayList<MiniGame> miniGames;
   private Graphics graphics;
   private Graphics2D graphics2D;

   // constructor
   public GamePanel() {

      super(new BorderLayout());
      setFocusable(true);

      // create 2 new players, and make it X's turn
      playerX = new Player(true, "X");
      turnPlayer = playerX;
      playerO = new Player(true, "O");

      // create tracking panel that will keep track of turns and stuff
      trackingPanel = new TrackingPanel(this);
      trackingPanel.setBorder(BorderFactory.createLineBorder(Color.red)); //!!
      System.out.println("line border added");

      // create panel that will hold the 9 mini games
      boardPanel = new BoardPanel(this);

      // add actionListeners to each button
      miniGames = boardPanel.getMiniGames();
      for (MiniGame mini : miniGames) {
         for (SquareButton button : mini.getSquares())
            button.addActionListener(this);
      }

      // add the tracking and board panels
      add(trackingPanel, BorderLayout.NORTH);
      add(boardPanel, BorderLayout.CENTER);
   }// end constructor

   public void actionPerformed(ActionEvent e) {

      // loop through mini games
      miniGameLoop: for (int gameNum = 0; gameNum < 9; gameNum++) {
         MiniGame mini = miniGames.get(gameNum);
         SquareButton[] buttons = mini.getSquares();

         // loop through buttons of each mini game
         for (int buttonNum = 0; buttonNum < 9; buttonNum++) {
            SquareButton button = buttons[buttonNum];

            // if user clicked on one of the squares on the board
            if (e.getSource() == button) {

               // if the space isn't already taken
               if (button.isEmpty()) {

                  //  mark the space with the player's letter
                  // !! removed
                  // ImageIcon icon = new ImageIcon(getClass().getResource(
                  // "/Images/" + turnPlayer.getLetter() + ".PNG"));
                  // button.setIcon(icon);
                  button.setText(turnPlayer.getLetter()); //!! added
                  button.setEmpty(false);

                  // change turns
                  changeTurns();

                  // exit loops
                  break miniGameLoop;
               }
            }
         }// end loop through squares
      }// end loop through minigames
   }// end actionPerformed method

   public static Player getPlayer(String letter) {
      if (letter == "X")
         return playerX;
      else
         return playerO;
   }

   public Player getPlayerTurn() {
      return turnPlayer;
   }

   public TrackingPanel getTrackingPanel() {
      return trackingPanel;
   }

   /* RELEVANT */
   public void changeTurns() {
      if (turnPlayer == playerX)
         turnPlayer = playerO;
      else
         turnPlayer = playerX;

      trackingPanel.updateTurn();
   }
}// end class GamePanel

class BoardPanel extends JPanel {

   private ArrayList<MiniGame> miniGames;

   // constructs main panel and places all 9 mini games inside
   public BoardPanel(GamePanel gp) {
      super(new GridLayout(3, 3));

      // add miniGames to arrayList
      miniGames = new ArrayList<MiniGame>(9);
      for (int i = 1; i <= 9; i++)
         miniGames.add(new MiniGame(gp, i));

      // add minigames to board
      for (MiniGame mini : miniGames)
         add(mini);
   }

   public void reset() {
      for (MiniGame mini : miniGames)
         mini.clear();
   }

   public ArrayList<MiniGame> getMiniGames() {
      return miniGames;
   }
}

@SuppressWarnings("serial")
class TrackingPanel extends JPanel {

   /* TURN STUFF */
   private JPanel turnPanel; // turns panel to keep track of whose turn it is
   private JLabel turnLabel;
   private String turn;

   /* OTHER */
   private GamePanel gamePanel;

   public TrackingPanel(GamePanel gamePan) {

      setLayout(new GridLayout(1, 4));
      setBorder(BorderFactory.createMatteBorder(2, 2, 4, 2, Color.BLACK));

      gamePanel = gamePan;

      /* THIS PANEL DISPLAYS THE TEXT */
      turnPanel = new JPanel(new GridLayout(2, 1));
      turn = gamePanel.getPlayerTurn().getLetter();
      turnLabel = new JLabel("      Player " + turn + "'s turn");
      turnPanel.add(turnLabel);
      add(turnPanel);

   }// end constructor

   /* THIS IS WHERE THINGS GO WRONG */
   public void updateTurn() {

      turn = gamePanel.getPlayerTurn().getLetter();
      turnLabel.setText("      Player" + turn + "'s turn");
      System.out.println(turn);
   }
}

class MiniGame extends JPanel {

   private SquareButton[] squares;
   private SquareButton[] line1, line2, line3, line4, line5, line6, line7,
         line8;
   private ArrayList<SquareButton[]> lines;
   private int ThreeinARowButtonCount;
   private int panelNum;
   private TrackingPanel trackingPanel;
   private int[] winningLine;
   private Player winner;
   private boolean gameIsOver;
   private Image gameOverIcon;

   public MiniGame(GamePanel gp, int num) {

      // setlayout of the mini games
      super(new GridLayout(3, 3));
      setFocusable(true);
      setPreferredSize(new Dimension(220, 220));

      // setPreferredSize(new Dimension(100,100));
      trackingPanel = gp.getTrackingPanel();
      panelNum = num;

      if (panelNum == 1)
         setBorder(BorderFactory.createMatteBorder(0, 0, 2, 2, Color.BLACK));
      else if (panelNum == 2)
         setBorder(BorderFactory.createMatteBorder(0, 2, 2, 2, Color.BLACK));
      else if (panelNum == 3)
         setBorder(BorderFactory.createMatteBorder(0, 2, 2, 0, Color.BLACK));
      else if (panelNum == 4)
         setBorder(BorderFactory.createMatteBorder(2, 0, 2, 2, Color.BLACK));
      else if (panelNum == 5)
         setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.BLACK));
      else if (panelNum == 6)
         setBorder(BorderFactory.createMatteBorder(2, 2, 2, 0, Color.BLACK));
      else if (panelNum == 7)
         setBorder(BorderFactory.createMatteBorder(2, 0, 0, 2, Color.BLACK));
      else if (panelNum == 8)
         setBorder(BorderFactory.createMatteBorder(2, 2, 0, 2, Color.BLACK));
      else
         setBorder(BorderFactory.createMatteBorder(2, 2, 0, 0, Color.BLACK));

      // create list of buttons (each square)
      squares = new SquareButton[9];

      // create squares and add squares to mini game
      for (int i = 0; i < squares.length; i++) {
         squares[i] = new SquareButton(i);
         add(squares[i]);
      }
   }// end constructor

   public void clear() {
      // TODO this method was not present!!!!! Trying to reconstruct it

   }

   public int getPanelNum() {
      return panelNum;
   }

   public SquareButton[] getSquares() {
      return squares;
   }

   public boolean isOver() {
      return gameIsOver;
   }
}

class SquareButton extends JButton {

   private boolean empty;
   private String letter;
   private int squareNum;

   public SquareButton(int num) {
      empty = true;
      squareNum = num;

      if (num == 0)
         setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, Color.BLACK));
      else if (num == 1)
         setBorder(BorderFactory.createMatteBorder(0, 1, 1, 1, Color.BLACK));
      else if (num == 2)
         setBorder(BorderFactory.createMatteBorder(0, 1, 1, 0, Color.BLACK));
      else if (num == 3)
         setBorder(BorderFactory.createMatteBorder(1, 0, 1, 1, Color.BLACK));
      else if (num == 4)
         setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
      else if (num == 5)
         setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, Color.BLACK));
      else if (num == 6)
         setBorder(BorderFactory.createMatteBorder(1, 0, 0, 1, Color.BLACK));
      else if (num == 7)
         setBorder(BorderFactory.createMatteBorder(1, 1, 0, 1, Color.BLACK));
      else
         setBorder(BorderFactory.createMatteBorder(1, 1, 0, 0, Color.BLACK));

   }

   public String getLetter() {
      return letter;
   }

   public boolean isEmpty() {
      return empty;
   }

   public void setEmpty(boolean em) {
      empty = em;
   }

   public int getSquareNum() {
      return squareNum;
   }
}

class Player {

   private boolean human; // indicates if player is human or cpu
   private int score;
   private String letter;

   // constructor
   public Player(boolean hum, String let) {

      // player is human or computer
      human = hum;
      letter = let;
   }

   /* PLAYER METHODS */
   public boolean isHuman() {
      return human;
   }

   public void setHuman(boolean h) {
      human = h;
   }

   public String getLetter() {
      return letter;
   }
}

但有趣的是,turnLabel 改变了它的文本,就像上面这个例子中应该的那样。所以现在你必须尝试隔离你的错误,因为它可能在代码中被遗漏了。正如您在问题中提到的那样,它可能与并发有关:

2)这是什么意思:“我想知道您的问题是否是并发问题,您正在 Swing 事件线程上执行长时间运行的过程,这会阻止您的标签更新其文本。” 我在别的地方读到了。

所以也许你有一个长时间运行的过程,你没有在上面的代码中向我们展示。

此外,您的代码过度使用静态字段反模式。大多数静态字段应该是静态的。

于 2013-07-08T22:43:46.297 回答