Качайте, как правильно обновить пользовательский интерфейс - PullRequest
8 голосов
/ 07 февраля 2011

Как правильно обновить пользовательский интерфейс после выполнения некоторых операций на Swing?

Например, после нажатия кнопки вызывается метод, который может быть почти мгновенным или занимать несколько секунд.На самом деле вся логика приложения выполняется удаленно через веб-сервис, поэтому нормально немного подождать, пока приложение ответит.

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

myButton.addActionListener(new java.awt.event.ActionListener() {
   public void actionPerformed(java.awt.event.ActionEvent evt) {
       //callWebService();
       //do stuff
       //updateUI(); // <----- repaint? revalidate? what?
   }
});

Моя текущая реализация вызывает метод updateUI, который внутренне вызывает validate () и repaint () для родительского компонента, который содержит пользовательский интерфейс.Это работает, но иногда я вижу мерцание экрана.Я делаю это неправильно?Есть ли лучший способ сделать это?

Ответы [ 4 ]

5 голосов
/ 07 февраля 2011

Правильный способ будет использовать SwingWorker, но если вы хотите сделать это вручную, вам придется реализовать следующий шаблон:

@Override public void actionPerformed(java.awt.event.ActionEvent evt) {
  new Thread() {
    @Override public void run () {
      //callWebService();
      //do stuff
      SwingUtilities.invokeLater(new Runnable(){
        @Override public void run() {
          //updateUI(); // <----- repaint? revalidate? what?
        }
      });
    }
  }.start();
}

Для вопроса перерисовки / повторной проверки обычно звоните revalidate() тогда repaint().это, конечно, только для компонента, который вы рисуете вручную.Для компонентов, которые вы используете повторно, просто вызовите их методы изменения значений.

4 голосов
/ 07 февраля 2011

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

  • Несмотря на то, что поддержание отзывчивости пользовательского интерфейса не является частью первоначального вопроса, в любом случае, это хорошая практика (я не могу придумать единственной веской причины заблокировать EDT с длительной обработкой.)
  • Он предоставляет метод done(), который может быть реализован и который будет выполнен в EDT по умолчанию после завершения задачи, избавляя от необходимости вручную оборачивать вещи в invokeLater()
  • Он более расширяемый, предоставляя структуру, позволяющую легко добавлять информацию, такую ​​как прогресс, позже, если это так желательно.

Я видел много ненавистников SwingWorker в целом в последнее время, и я не понимаю, почему. Это хорошо разработанный, расширяемый класс специально для таких целей, как этот, который хорошо работает. Да, вы можете обернуть вещи в потоки и запустить их, а другие методы обернуть в invokeLater(), но зачем изобретать велосипед, если есть лучший, доступный бесплатно?

1 голос
/ 07 февраля 2011

Перенесите долгосрочное задание в другой поток.Отправьте события обратно в поток обработки событий AWT (EDT), чтобы обновить графический интерфейс с java.awt.EventQueue.invokeLater.

0 голосов
/ 07 февраля 2011

Обычно вам не нужно ничего делать: если вы используете методы компонентов колебания или методы их модели, запускаются необходимые события, и графический интерфейс должен обновляться автоматически.

Это не будет так, если вы определите свои собственные модели (и забудете запустить необходимые события, но тогда это ошибка в ваших моделях, и она должна быть исправлена ​​там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...