Thread.sle и перекрасить - PullRequest
       18

Thread.sle и перекрасить

2 голосов
/ 03 декабря 2010

У меня есть панель, которая отображает текст. Я хочу, чтобы панель изменила свой текст, а затем приостановила приложение, прежде чем что-либо еще произойдет. Я использую Thread.sleep (1000). Однако по какой-то причине приложение не заканчивает рисовать панель до вызова Thread.sleep (текст не изменяется). Я также попробовал это:

board.invalidate();
board.setLeftMessage("Not");
board.setRightMessage("Here");
board.revalidate();
Date current = new Date();
long timeNow = current.getTime();
Date newDate = new Date(timeNow + 1000);
while (current.before(newDate))
    current = new Date();

но там тоже не повезло. У кого-нибудь есть предложение? Большое спасибо.

Ответы [ 5 ]

8 голосов
/ 03 декабря 2010

Вы блокируете поток обработки событий AWT (EDT).EDT обрабатывает события перерисовки и ввода, поэтому ваш код не должен быть многопоточным (что было бы практически невозможно)Используйте javax.swing.Timer, чтобы отправить событие позже по EDT.(Не путайте javax.swing.Timer с java.util.Timer!)

3 голосов
/ 03 декабря 2010

Взгляните на javax.swing.Timer - я думаю, это то, что вам нужно для этого.

РЕДАКТИРОВАТЬ # 1: Документация Sun \ Oracle фактически предлагает использовать таймеры Swing с здесь .

В общем, мы рекомендуем использовать Swing таймеры, а не общего назначения таймеры для задач, связанных с GUI, потому что Все таймеры свинга одинаковы, существующий поток таймера и Задача, связанная с GUI, автоматически выполняется в потоке событий. Тем не менее, вы можете использовать таймер общего назначения, если вы этого не сделаете планируем прикоснуться к GUI от таймер, или нужно выполнять долго обработка.

РЕДАКТИРОВАТЬ # 2: Похоже, есть несколько хороших основных учебников здесь .

РЕДАКТИРОВАТЬ # 3: Удалено предложение использовать TimerTask - в этом случае это будет плохая идея.

2 голосов
/ 03 декабря 2010

Ваша "долгосрочная задача" должна выполняться в отдельном потоке.Затем, когда вы хотите обновить графический интерфейс, вам нужен код для запуска в потоке диспетчеризации событий (EDT).Затем вы можете попросить отдельный поток перевести его в спящий режим, и это не повлияет на рисование графического интерфейса.

Для этого вы сможете использовать SwingWorker.Прочитайте раздел учебника по Swing по Concurrency для получения дополнительной информации.

Если вам не нравится использование SwingWorker, вам нужно создать свой собственный поток и обернуть код, который обновляетГрафический интерфейс в SwingUtilities.invokeLater ().

1 голос
/ 22 января 2013

Thread.sleep - это долгосрочное задание.Когда вы выполняете такую ​​задачу в EDT, она блокирует выполнение всех запросов на перерисовку.Все запросы на перерисовку, находящиеся на рассмотрении и отправленные во время фазы ожидания, ставятся в очередь для дальнейшей обработки.

В результате, когда EDT выходит из фазы sleep, он объединяет все такие запросы на перерисовку (если объединение выполняетсявключен, который является свойством по умолчанию) в один перекрас, который выполняется.Если объединение не включено, то все запросы в очереди выполняются последовательно без промежутка времени.В результате кажется, что пользовательский интерфейс не обновился.

Для исправления ситуации используйте timer, который периодически срабатывает через определенные промежутки времени.

1 голос
/ 03 декабря 2010

Вы не должны обновлять компоненты GUI из вашего основного потока.Используйте SwingUtilities.invokeLater, чтобы запланировать обновление в цепочке событий:

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    board.invalidate();
    board.setLeftMessage("Not");
    board.setRightMessage("Here");
    board.revalidate();
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...