views:

238

answers:

4

Hello, my GUI locks up because I need to update it through the EDT, however, I need to also pass a variable that is being updates with the GUI:

while ((message = this.in.readLine()).startsWith("NUMPLAYERS"))
{
    numOfPlayers = Integer.parseInt(message.split(":")[1]);
    numPlayers.setText("There are currently " + numOfPlayers + " players in this game");
}

This does not work. I need to set the text in the EDT but I cannot pass numOfPlayers to it without declaring it as final (which I don't want to do, because it changed as new players join the server)

+4  A: 

The easiest solution would be to use a final temporary variable:

final int currentNumOfPlayers = numOfPlayers;
EventQueue.invokeLater(new Runnable() {
    public void run() {
       numPlayers.setText("There are currently " + 
               currentNumOfPlayers + " players in this game");
    }
});
Michael Myers
In this case, it just needs the local variable to be defined at an appropriate point (and made final).
Tom Hawtin - tackline
+1  A: 

You have to make it final or have the Runnable reference a field (class varable). If referencing a field make sure that it's thread safe (via synchronized or volatile).

Steve Kuo
How would I reference the class variable? That would be ideal.
Logan Serman
+1  A: 

How about this:

while ((message = this.in.readLine()).startsWith("NUMPLAYERS")) {
    numOfPlayers = Integer.parseInt(message.split(":")[1]);
    final newText = "There are currently " + numOfPlayers + " players in this game";
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            numPlayers.setText(newText);
        }
    });
}

NOTE: I assume that the OP has a good reason for not marking numOfPlayers as final, perhaps that it is changed later in the same while loop in code that's not relevant to the question, so not shown. And thus that numOfPlayers is declared before the while loop.

Without this assumption, I wouldn't make the additional variable newText.

Eddie
Missing String before badly capitalised newtext. Probably can make numOfPlayers itself final after putting declaration in the correct place.
Tom Hawtin - tackline
@Tom Hawtin: I updated my answer ... the OP says that he has a good reason for not making numOfPlayers final. I assume that this ties into why the OP's sample does not show the variable declaration. And because you complained, I changed the capitalization of newText. :)
Eddie
A: 

Define this class outside of your method:

public abstract class MyRunnable implements Runnable {
    protected int var;
    public MyRunnable (int var) {
        this.var = var;
    }
}

Now your code can look like this:
SwingUtilities.invokeAndWait(new MyRunnable(5) {
    @Override
    public void run() {
        //numPlayers.setText("There are currently " + var + " players in this game");
    }
});

(For the purposes of this example, I am assuming that there is a good reason why using a locally scoped final temp variable will not work. I honestly can't think of any reason for that restriction, though.)

jsight