简体   繁体   English

setText为什么不更新JLabel?

[英]Why isn't setText updating the JLabel?

I've checked on the other threads here and haven't found a solution. 我在这里检查了其他线程,但没有找到解决方案。

1) The JFrame is setVisible(true). 1)JFrame是setVisible(true)。

2) What does this mean: "I wonder if your problem is a concurrency issue, that you are doing a long-running process on the Swing event thread and that this is preventing your label from updating its text." 2)这意味着什么:“我想知道您的问题是否是并发问题,您正在Swing事件线程上运行一个长时间运行的进程,并且这阻止了标签更新其文本。” I read that somewhere else. 我在其他地方读过。

3) I haven't initialized multiple times the JPanel that contains the label. 3)我没有多次初始化包含标签的JPanel。

EDIT: 4) updateTurn is called from the JPanel that contains TrackingPanel (ie gamePanel ). 编辑:4)从包含TrackingPanel (即gamePanel )的JPanel调用gamePanel I call the method changeTurns(); 我称方法changeTurns(); and here's the code for that: 这是该代码:

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

    trackingPanel.updateTurn();
}   

Here's the relevant code in full: 这是完整的相关代码:

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

Before updateTurn() is called, turnLabel says "PlayerX's turn". updateTurn()之前, turnLabel说“ PlayerX的转弯”。 After, it should say "PlayerO's turn". 之后,应该说“ PlayerO轮到我了”。 By printing out turn (I get the string 'O', instead of 'X'), I know that whats being displayed ("PlayerX's turn") is not what should be displayed ("PlayerO's turn"). 通过打印turn牌(我得到的是字符串'O'而不是'X'),我知道所显示的内容(“ PlayerX的转弯”)不是应该显示的内容(“ PlayerO的转弯”)。

Thanks in advance you smartypants! 在此先感谢您的支持!

EDIT. 编辑。 Tried giving SSCCE but don't know how to include image files. 尝试提供SSCCE,但不知道如何包含图像文件。 Sorry! 抱歉!

Try using this: 尝试使用此:

 private void setText(final JLabel label, final String text){
    label.setText(text);
    label.paintImmediately(label.getVisibleRect());
 }

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

I've changed your code so that it doesn't require images, and now the turnLabel has been added. 我已经更改了您的代码,使其不需要图像,现在添加了turnLabel。 It is still too big, but it runs and shows some behaviors: 它仍然太大,但是可以运行并显示一些行为:

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

But interestingly, the turnLabel changes its text as it is supposed to in this example above. 但有趣的是,turnLabel会像上面的示例一样更改其文本。 So now you must try to isolate your error as it may be in code left out. 因此,现在您必须尝试隔离错误,因为它可能在遗漏的代码中。 Perhaps it has something to do with concurrency as you mention in your question: 就像您在问题中提到的那样,这可能与并发有关:

2) What does this mean: "I wonder if your problem is a concurrency issue, that you are doing a long-running process on the Swing event thread and that this is preventing your label from updating its text." 2)这意味着什么:“我想知道您的问题是否是并发问题,您正在Swing事件线程上运行一个长时间运行的进程,并且这阻止了标签更新其文本。” I read that somewhere else. 我在其他地方读过。

So perhaps you have a long running process that you've not shown us in the code above. 因此,也许您的运行过程很漫长,而您没有在上面的代码中向我们展示。

Also, your code has an over-use of static fields anti-pattern. 另外,您的代码过度使用了静态字段反模式。 Most of the fields that are static should not be static. 大部分都是静态字段应该是一成不变的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM