Передача переменных в поток обработки событий - PullRequest
5 голосов
/ 16 апреля 2009

Мой GUI блокируется, потому что мне нужно обновить его через EDT, однако мне также нужно передать переменную, которая обновляется через GUI:

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

Это не работает. Мне нужно установить текст в EDT, но я не могу передать ему numOfPlayers, не объявив его как окончательный (что я не хочу делать, потому что он изменился, когда новые игроки присоединились к серверу)

Ответы [ 4 ]

10 голосов
/ 16 апреля 2009

Самое простое решение - использовать временную переменную final:

final int currentNumOfPlayers = numOfPlayers;
EventQueue.invokeLater(new Runnable() {
    public void run() {
       numPlayers.setText("There are currently " + 
               currentNumOfPlayers + " players in this game");
    }
});
2 голосов
/ 16 апреля 2009

Вы должны сделать его окончательным или иметь Runnable ссылку на поле (класс varable). При обращении к полю убедитесь, что оно потокобезопасно (через синхронизированное или энергозависимое).

1 голос
/ 16 апреля 2009

Как насчет этого:

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

ПРИМЕЧАНИЕ. Я полагаю, что у ОП есть веская причина не отмечать numOfPlayers как окончательное, возможно, позже оно будет изменено в том же цикле while в коде, который не относится к вопросу, поэтому не показан. И, таким образом, numOfPlayers объявляется перед циклом while.

Без этого предположения я бы не сделал дополнительную переменную newText.

0 голосов
/ 16 апреля 2009

Определите этот класс вне вашего метода:

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

(Для целей этого примера я предполагаю, что есть веская причина, по которой использование конечной временной переменной с локальной областью действия не будет работать. Однако я, честно говоря, не могу придумать причину такого ограничения.) *

...