Индикатор свинга Java с проблемой EDT - PullRequest
6 голосов
/ 13 августа 2010

Это для экспертов по свингам.Я потратил немало времени на решение этой проблемы, поэтому мне потребуется несколько строк, чтобы объяснить эту проблему.

У меня есть отдельное приложение java swing (java 6).В моем приложении у меня есть рамка с группой переключателей.У меня есть одно действие, связанное со всеми кнопками в группе.Действие проверяет, какой переключатель выбран, и выполняет некоторую работу.«Работа» включает в себя некоторые фоновые вычисления, а также рисование в двух других фреймах в моем приложении.Фоновые вычисления являются многопоточными.

Я хотел бы отобразить индикатор выполнения, когда пользователь выбирает одну из переключателей.Однако, когда выбран переключатель, в то время как выполняется действие с переключателем, индикатор выполнения никогда не появляется.Я пробовал индикаторы типа jdialog, стеклянные панели и т. Д. Ни одна из них не появляется, пока «работа» не будет завершена.Похоже, это происходит потому, что Swing не заканчивает рисование переключателя, пока не завершится «работа» в соответствующем действии.А поскольку EDT выполняет только одну операцию одновременно, диалоговое окно индикатора выполнения (или стеклянная панель) никогда не отображается.

Затем я попытался использовать SwingWorker, чтобы выполнить всю эту «работу».Запустите индикатор выполнения (или активируйте стеклянную панель), запустите SwingWorker и закройте индикатор выполнения (или деактивируйте стеклянную панель) в методе done () для SwingWorker.Похоже, это хорошо отображает индикатор выполнения, но рисование, которое является частью «работы», иногда не завершается, из-за чего у меня появляются некоторые артефакты рисования (метод paintComponent довольно сложен, поэтому не хочу воспроизводить его здесь).Артефакты исчезнут, если я изменю размеры окна.Фактически, это происходит, если я использую класс, который расширяет Thread вместо SwingWorker.Это все потому, что Swing не является потокобезопасным, и я пытаюсь выполнить работу с графическим интерфейсом из потока, отличного от EDT.Я понимаю эту часть.

Что мне делать?«Работа» занимает около 30 секунд, и это кажется слишком долгим, чтобы не показывать пользователю какое-либо указание на то, что программа работает.Я также попытался изменить курсор на курсор ожидания и столкнулся с теми же проблемами, что и выше.Единственное, что я могу сделать, - это отключить фрейм и установить для заголовка фрейма такой текст, как «работает ...»

Кто-нибудь видел эту проблему раньше?

Ответы [ 2 ]

4 голосов
/ 13 августа 2010

Я думаю, что вы правы, выполняя работу в ветке SwingWorker, но вам не следует пытаться рисовать там.

Я бы склонен:

  • У ActionListener покажите () индикатор выполнения, выключите свингера, затем выйдите из

  • Пусть рабочий поток выполняет работу и периодически вызывает repaint () для компонента индикатора выполнения (это гарантированно безопасен для потока)

  • Индикатор выполнения имеет собственный PaintComponent (который будет автоматически вызываться в EDT). При необходимости это может прочитать некоторую переменную, которая обновляется рабочим потоком для измерения прогресса

  • Когда рабочий поток завершает свою работу, вызовите invokeLater () для запуска функции окончательного закрытия на EDT, которая скроет индикатор выполнения и выполнит любую другую очистку, связанную с GUI / покажет сообщение о завершении для пользователь и т. д.

4 голосов
/ 13 августа 2010

Когда вы перенесли работу из EDT в мастер качелей (что было правильно сделать), звучит так, что и работа, и картина были перенесены на работника качелей. Картина все еще должна происходить на EDT. Вы можете добиться этого с помощью SwingUtilities.invokeLater для вызова перерисовки из фонового потока или с помощью SwingWorker.publish (V ...) , который будет принимать уведомления из вашего рабочего потока и делать их доступными в EDT с помощью метода шаблона SwingWorker.process (V ...) (который вы переопределяете). Переопределение process может обрабатывать промежуточные уведомления, перекрашивая часть экрана, обновляя прогресс или предпринимая другие необходимые действия по желанию. Любые изменения пользовательского интерфейса будут видны, не дожидаясь завершения остальной части работы.

...