2

I have a chess game I'm trying to make, and I'm trying to call the repaint() method on one of my JFrames in the game loop. This particular JFrame shows the total kills for each player. I'm pretty sure repaint() is actually being called, but for some reason it doesn't seem to be updating my JLabels correctly, which are supposed to hold the number of kills values for each player.

Here's my code for the custom JFrame extension class which houses the JLabels representing the kills.

private ChessGame game;
private JPanel killsPanel;
private String p1kills;
private String p2kills;
private JLabel kills;
private JLabel p1, p2;
private JLabel p1NumKills = new JLabel();
private JLabel p2NumKills = new JLabel();


//the player's kill values are increasing and registering, just not within the jlabels representing them
public KillsFrame(ChessGame game){
    this.game = game;
    killsPanel = new JPanel(new MigLayout("", "[center][right][left][c]", "[top][center][b]"));
    kills = new JLabel("KILLS");
    p1 = new JLabel(game.getCurrentPlayer().getName() + " - ");
    p2 = new JLabel(game.getOtherPlayer().getName() + " - ");

    //this is the part that should be working but isn't.
    //p1kills and p2kills aren't being updated or something.
    p1kills = "" + game.getCurrentPlayer().getKills();
    p2kills = "" + game.getOtherPlayer().getKills();
    p1NumKills.setText(p1kills);
    p1NumKills.setText(p2kills);

    killsPanel.add(kills, "span");
    killsPanel.add(p1);
    killsPanel.add(p1NumKills, "wrap");
    killsPanel.add(p2);
    killsPanel.add(p2NumKills, "wrap");

    killsPanel.setBackground(Color.lightGray);
    add(killsPanel);
    pack();
    setTitle("Scoreboard");
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setResizable(true);
    setVisible(true);
    setLocationRelativeTo(null);
}

Then I just call this frame's repaint() in a main method in a different class:

public static void main(String[] args) throws InterruptedException {

    JFrame gameFrame = new ChessMain();
    gameFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    gameFrame.pack();
    gameFrame.setResizable(true);
    gameFrame.setLocationRelativeTo(null);
    gameFrame.setVisible(true); 
    gameFrame.setTitle("Chess X");

    LoginFrame loginFrame = new LoginFrame(((ChessMain) gameFrame).getGame());

    System.out.println(((ChessMain) gameFrame).getGame().toString());
    System.out.println(((ChessMain) gameFrame).getGame().currentPlayer.getName()+ ", it's your turn.");

    //this is what creates the kills frame.
    KillsFrame kf = new KillsFrame(((ChessMain) gameFrame).getGame());

    while(true){

        ((ChessMain) gameFrame).getGame().run();
        kf.repaint();//*************************************
        Thread.sleep(1);

    }

}

Any and all help is greatly appreciated.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • 2
    See also this [example](http://stackoverflow.com/a/2562685/230513) and [variation](http://stackoverflow.com/a/2563350/230513). – trashgod Jun 25 '12 at 01:10
  • 2
    You don't need to call `repaint()` to display text changes in a JLabel as the label will do this on its own when `setText(...)` is called. – Hovercraft Full Of Eels Jun 25 '12 at 01:11
  • 2
    More importantly: your game loop, the `while (true) {...}` bit of code is not necessary and actually counter productive. Get rid of that code and instead use Swing's event-driven architecture to do this for you. – Hovercraft Full Of Eels Jun 25 '12 at 01:13
  • 2
    And for another variation, please see [this](http://stackoverflow.com/a/4687759/522444). – Hovercraft Full Of Eels Jun 25 '12 at 01:24
  • I once given a full explanation on why calling `repaint` and `sleep` does not what you expect. See [this answer](http://stackoverflow.com/questions/11088910/timing-with-swing-animation/11090056#11090056) – Robin Jun 25 '12 at 05:59

1 Answers1

1

Your error lies when you are trying to "sleep" your main thread. This is bound to cause errors if not make your GUI non-responsive. Your best bet is to use the swing.Timer class (tutorial here http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html). Fire events at regular intervals to repaint(). This will result in a smooth animation.

if for some reason you Have to sleep a thread in a swing program, create a new thread using the SwingWorker class (And not otherwise). see http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List)

Vedant Agarwala
  • 18,146
  • 4
  • 66
  • 89