2015-08-16 3 views
-1

EDIT: Упрощен мой код.GUI не обновляется после вызова метода GUI в другом потоке

Это основной класс, который инициализирует потоки графического интерфейса и сервера.

public class Main { 
    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException { 
    Runnable tGUI = new TransceiverGUI(); 
    Runnable server = new Server(tGUI); 
    new Thread(tGUI).start(); 
    new Thread(server).start(); 
    } 
} 

Теперь в моем public class TransceiverGUI extends javax.swing.JFrame implements Runnable классе, у меня есть метод со следующим:

protected boolean incomingFileRequest(String filename, long filesize, String user) throws InterruptedException, InvocationTargetException { 
     /* .... code logic which executes .... */ 
     /* UPDATE GUI HERE DOES NOT WORK */ 
     LabelProgress.setForeground(Color.red); 
     LabelProgress.setText("Receive Progress"); 
    } 

Когда incomingFileRequest вызывается из класса GUI (из любого EventListener) она прекрасно работает и графический интерфейс обновлено.

Однако, когда я вызываю incomingFileRequest из класса/потока Server, код запускается и возвращает правильное значение, но графический интерфейс пользователя не обновляется.

Сервер нить называет это так: // POPUP with request boolean answer = gui.incomingFileRequest(message.getMessage(), message.getFileSize(), message.senderIPAddress);

Я поставил код, который обновляет графический интерфейс в блоке, который создает новую нить вроде этого:

Thread t = new Thread() { 
public void run() { 
    LabelProgress.setForeground(Color.red); 
    LabelProgress.setText("Receive Progress"); 
    repaint(); 
} 
}; 
t.start(); 

Я также попытался javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { /* update GUI code */ } });.

Мой вопрос: как я могу вызвать метод (который обновляет графический интерфейс) в классе GUI из другого потока? Помня о том, что код выполнен отлично, элементы GUI просто не обновляются.

Любая помощь была бы принята с благодарностью.

+5

** Swing одиночный с резьбой **. Вы просто не можете использовать элементы Swing из нескольких потоков. Это не разрешено**. Вы ** должны ** ограничивать доступ к компонентам Swing к EDT. –

+3

I второй @ комментарии BoristheSpider выше. Кроме того, ваша проблема представляет собой несколько сложную проблему для связи между различными классами с использованием разных потоков, и для этого может потребоваться создание и публикация [mcve], чтобы мы могли полностью понять вашу проблему и ее возможные причины. Пожалуйста, прочитайте ссылку. –

+1

Что касается вашего редактирования выше, если это связано с моим комментарием выше, то я не думаю, что вы понимаете, о чем я прошу. Опять же, пожалуйста, прочитайте ссылку, поскольку она полностью объяснена там. –

ответ

2

С вашего поста

Когда incomingFileRequest вызывается из класса GUI (из любого EventListener) он прекрасно работает и графический интерфейс обновляется.

Однако, когда я вызываю incomingFileRequest из класса/потока сервера, код запускается и возвращает правильное значение, но графический интерфейс пользователя не обновляется.

Это именно то, что некоторые ppl пытались объяснить вам в комментариях. Все обновления GUI должны выполняться в потоке графического интерфейса - EDT.

Отправка сообщения о событии - это тот, который обрабатывает ваш «слушатель», поэтому графический интерфейс пользователя обновляется. Чтобы обновить ваш gui из другого потока, вам нужно просто «запланировать» ваши изменения, которые должны быть выполнены в EDT. Для этого просто добавьте код модификации GUI в класс Runnable и передайте его в EDT с помощью метода SwingUtilities.invokeLalater(Runnable). Таким образом, ваш GUI будет обновляться как можно скорее

Вы также упоминали, что

Я также попытался javax.swing.SwingUtilities.invokeLater (новый Runnable) { общественного недействительными запуска() {/ * GUI обновление (код * /}}) ;.

И что было результатом? Потому что это именно то, как это должно быть сделано. Если это не работает для вас, есть еще одна проблема с вашим кодом, либо тело вашего метода ждет каких-то внешних обновлений, либо запланировано в другой момент, чем вы думаете.

+0

Именно поэтому я так смущен. Я пробовал вызывать 'SwingUtilities.invokeLalater (Runnable) 'из метода в классе GUI, который вызывается потоком. Я также попытался называть его завернутым в 'SwingUtilities.invokeLalater (Runnable)' из потока. Ничего не работает. – EfVonZee

+0

Чем проблема находится где-то в другом месте, она ДОЛЖНА работать – Antoniossss

+0

Хорошие предложения. 1+ –

0

Изначально я был

public class Main { 

    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException { 

    Runnable tGUI = new TransceiverGUI(); 
    Runnable server = new Server(tGUI); 

    System.out.println("Starting GUI..."); 
    new Thread(tGUI).start(); 
    System.out.println("Starting Server..."); 
    new Thread(server).start(); 
    } 
} 

После многих часов поиска решений я просто поменялись местами вокруг, как я полностью изменила способ, которым я прошел параметр в резьбе. Как вы можете видеть в следующем (рабочем) коде, я сначала создаю поток сервера, а затем передаю его как параметр в поток GUI. Я также изменил соответствующие конструкторы, чтобы соответственно принять параметры.

После смены все работает отлично. На самом деле у меня нет причин, почему это изменение решило мою проблему.

public class Main { 

     public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, UnknownHostException { 

     Runnable server = new Server(); 
     Runnable tGUI = new TransceiverGUI(server); 

     System.out.println("Starting Server..."); 
     new Thread(server).start(); 
     System.out.println("Starting GUI..."); 
     new Thread(tGUI).start(); 
     } 
    }