2013-07-08 132 views
0

我检查了其他线程在这里,还没有找到解决方案。为什么setText没有更新JLabel?

1)JFrame是setVisible(true)。

2)这是什么意思:“我想知道你的问题是否是一个并发问题,你在Swing事件线程上做了一个长时间运行的过程,并且这阻止了你的标签更新它的文本。我在其他地方读过。

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

编辑: 4)updateTurn从JPanel调用,它包含TrackingPanel(即gamePanel)。我所说的方法changeTurns();和这里的代码为:

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

    trackingPanel.updateTurn(); 
} 

下面是相关的代码全部: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); 
    } 
} 

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

在此先感谢您smartypants!

编辑。试图给SSCCE,但不知道如何包含图像文件。抱歉!

+4

你在哪里调用updateTurn()? –

+0

当你尝试在添加标签后添加一个对'validate'的调用时会发生什么? – crand6

+0

我只是在添加标签后写'validate()'写入吗?如果是这样,什么都没发生另外,我应该注意,JLabel不应该被添加。 setText()应该改变当前JLabel的文本。我在上面的问题中拿出了第二个panel.add(JLabel)调用。 –

回答

3

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

+0

对不起,我不熟悉这种方法。我发现它应该包含在main()方法中,但是我在SwingUtilities方法中放入了什么? –

+0

setText部分应该放置在那里,这将确保更新Swing组件将在正确的线程中完成。 –

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事件线程,并且这阻止了您的标签更新其文本。“我在其他地方读过。

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

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

5

尝试使用这样的:

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

不,绝对不需要 - 加上它可能会造成灾难性的影响,如果关闭美国东部时区 – kleopatra

+2

这完全符合我的需要,因为我立即在后面运行悬挂功能。 – Robobenklein

+0

拯救生命! :D –