Почему покраска компонента задерживается?

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

JPanel somePanel = getSomePanel();
somePanel.setBackground(Color.BLUE);
Object lock = new Object();
synchronized (lock) {
    try {
        lock.wait(5000);
    }
    catch (InterruptedException exc) { }
}
// Do other stuff

Но вместо этого он ждет пять секунд и затем окрашивает компонент в синий цвет.

  • Зачем сначала ждать, потом красить в синий цвет, а не наоборот? (Думаю, это как-то связано с механизмом Swing...?)
  • Как «изменить этот порядок»?

person MC Emperor    schedule 30.01.2013    source источник
comment
Не блокируйте EDT (поток отправки событий) — когда это произойдет, графический интерфейс «зависнет». Вместо вызова Thread.sleep(n) реализуйте Swing Timer для повторяющихся задач или SwingWorker для длительных задач. Дополнительные сведения см. в разделе Параллелизм в Swing.   -  person Andrew Thompson    schedule 30.01.2013
comment
@AndrewThompson, но у меня это отлично работает. Без использования invokeLater() или invokeAndWait() это поведение также зависит от разных платформ?   -  person joey rohan    schedule 30.01.2013
comment
зависит от разных платформ? Платформы, JRE, моменты времени, влажность... Отсутствие редактирования GUI в EDT может привести к «непредсказуемому» поведению. Конечно, результат блокировки EDT является очень предсказуемым.   -  person Andrew Thompson    schedule 30.01.2013
comment
// Do other stuff Чтобы быстрее получить помощь, опубликуйте SSCCE.   -  person Andrew Thompson    schedule 30.01.2013
comment
Также см. этот аналогичный ответ и вариант   -  person David Kroukamp    schedule 30.01.2013
comment
@AndrewThompson: и не забывайте Look & Feel. Я помню этот, потому что я был сожжен этим раньше!   -  person Hovercraft Full Of Eels    schedule 30.01.2013
comment
@joeyrohan Извините, забыл добавить уведомление к последнему комментарию о «платформе». :П   -  person Andrew Thompson    schedule 31.01.2013


Ответы (3)


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

Пока вы ждете блокировки, GUI ничего не делает.

person Martin James    schedule 30.01.2013

Не выполняйте синхронизированный код с блокировкой потока событий Swing, поскольку все, что вы делаете, — это блокируете сам Swing и замораживаете графический интерфейс. Google "Параллелизм в Swing" для деталей. Сам я бы использовал для этого Swing Timer. Обратите внимание, что в вашем сообщении используется тег многопоточность, но вы на самом деле нигде не делайте многопоточность.

person Hovercraft Full Of Eels    schedule 30.01.2013
comment
насчет этого многопоточности: похоже, что он перемаркирован из поток. - person MC Emperor; 30.01.2013

Остальные правы, если вы ждете в потоке отправки событий, то этот поток тем временем не будет рисовать.

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

somePanel.paintImmediately(0, 0, somePanel.getWidth(), somePanel.getHeight());
person lbalazscs    schedule 30.01.2013