2015-01-13 3 views
0

Этот вопрос может быть дублирован, потому что я нашел много аналогичного вопроса, но не ответил на мою проблему: мне нужно обновить представление моего приложения SWING из разных SwingWorker. У меня есть класс вида с JTextArea и JTable, который мне нужно обновить во время выполнения Threads. В представлении также есть кнопка «Пуск», которая запускает все потоки. Контроллер прослушивает кнопка будет нажата, то запуск темы:Java Swing - обновление вида из нескольких потоков

public class MonitorPageController { 

    private MonitorPage monitorPage; 
    private List<Mission> missions; 

    class StartButtonListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      for (int i = 0; i < missions.size(); i++) { 
       MyWorker worker = new MyWorker(missions.get(i)); 
       worker.execute(); 
      } 
     } 
    } 

} 

Тогда я MyWorker класс, управлять моделью:

public class MyWorker extends SwingWorker<Integer, String> { 

    private Mission m; 

    //<dec> 
    Block block1 = new Block(); 
    Block block2 = new block(); 
    Block block3 = new Block(); 
    Block block4 = new Block(); 

    public MyWorker(Mission mission) { 
     this.m = mission; 
    } 

    @Override 
    protected Integer doInBackground() throws Exception { 
     //<exe> 
     block1.addObserver(block2); 
     block2.addObserver(block3); 
     block3.addObserver(block4); 
     block4.addObserver(block2); 
     block1.update(null, m); 

     return 4; 
    } 

} 

В конце концов у меня есть класс блок, где Мне нужно обновить GUI (JTable и JTextArea):

public class Block extends Node implements Observer { 


    public Mission run(Mission m) { 
     m.setStatus(Mission.UNEXECUTED); 

     // HERE I WANT TO NOTIGY THE VIEW OF THE CHANGE OF STATUS OF THE MISSION 

     return m; 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     Mission m = this.run((Mission) arg); 
     setChanged(); 
     notifyObservers(m); 
    } 
} 

EDIT: Миссия является простой класс с го e attribute: int status

Я уже пробовал с другим шаблоном наблюдателя: я установил миссию как наблюдаемую и MonitorPageController в качестве наблюдателя. Затем в методе setter статуса в классе Mission я добавил методы setChanged() и notifyObservers(). В конце в Observer (MonitoPageController) я применил метод update(), чтобы вызвать представление и обновить gui. Мне понравился этот путь, потому что он чист и прост в реализации, но теперь я не понимаю, почему после вызова notifyObserver() ничего не происходило, поэтому я отбросил это решение, даже если оно кажется правильным

+0

Почему бы не создать метод, который делает это в вашем графическом интерфейсе? Например, GUIClass.updateText() – CaffeineToCode

+0

Вы можете использовать SwingWorker как прокси-сервер между блоками и пользовательским интерфейсом, позволяя SwingWorker запускать PropertyChangeEvent или публиковать обновление ... – MadProgrammer

+0

Что такое миссия? – MadProgrammer

ответ

1

Обновление пользовательского интерфейса вызывающего SwingUtilities.invokeLater():

public class Block extends Node implements Observer { 


    public Mission run(Mission m) { 
     m.setStatus(Mission.UNEXECUTED);  
     SwingUtilities.invokeLater(new Runnable(){ 
      @Override   
      public void run(){ 
      //UPDATE UI HERE 
      } 
     });  
     return m; 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     Mission m = this.run((Mission) arg); 
     setChanged(); 
     notifyObservers(m); 
    } 
} 
+0

Единственная проблема, с которой я столкнулся бы, заключается в том, что она соединяет пользовательский интерфейс с узлом/блоком, который не может быть желательным. Лучшим решением было бы реализовать еще один шаблон наблюдателя, который действовал бы как уведомление о статусе, таким образом, фактическое не заботится о том, что вы сделали с уведомлением. Это означает, что вы можете. Используйте функциональность функций SwingWorker для синхронизации пользовательского интерфейса, поскольку в op уже есть один;) – MadProgrammer

+0

, как сказал MadProgrammer, это решение заставляет меня иметь экземпляр класса View в классе Block, проходящего SwingWorker. Я думаю, что может быть лучшее решение – Cardella

0

Я нашел возможное решение, может быть, лучшие идеи, но это работает сейчас: Создание SwingWorker в MonitorPageController я изменил конструктор проходящего в istance в MonitorPageController тоже.

MyWorker worker = new MyWorker(misssions.get(i), this); 

Тогда в классе MyWorker когда я создаю block1, block2 ... Я передаю им istance из MyWorker:

Block block1 = new Block(this); 
Block block2 = new Block(this); 
.... 

В том же классе (MyWorker) Я создал метод:

public void log(Mission m, String s) { 
    controller.log(m, s); 
} 

Контроллер - это объект MonitorPageController, который создал рабочего.

Теперь класс внутри блока, когда я хочу, чтобы уведомить об изменении статуса, я могу назвать:

parentWorker.log(mission, "some string"); 

В конце концов метод журнала() в MonitorPageController вызывает метод просмотра для обновления компонентов ... к настоящему времени, похоже, работает ...

Смежные вопросы