Я создаю Java-программу, которая загружает N элементов с сервера. Я хотел бы иметь рабочий индикатор выполнения, который показывает процент «уже загруженных элементов» / N. Прямо сейчас я обновляю значение индикатора выполнения, передавая потоку ссылку на объект GUI, но это делает код «некрасивым» (класс GUI создает поток, который содержит ссылку на сам GUI, создавая своего рода цикл). Есть ли способ лучше?
Обновить индикатор выполнения из рабочего потока
Ответы (4)
SwingWorker
в этом контексте имеет некоторые преимущества, как предлагается в этом примере.
Прочтите API JProgressBar и перейдите по ссылке на учебник Swing о том, как использовать индикаторы выполнения, чтобы получить рабочий пример.
Для того, чтобы убрать «петлю». Создайте интерфейс, расширяемый графическим интерфейсом пользователя, который передается рабочему потоку.
Один из шаблонов проектирования, который может быть здесь полезен, - это шаблон слушателя. Зарегистрируйте прослушиватель прогресса в рабочем потоке. Затем слушатель отвечает за отправку в графический интерфейс (или что-то еще, что может быть интересно в процессе).
Поскольку в такой ситуации маловероятно, что у вас будет несколько слушателей, часто лучше иметь только одного слушателя (снижает сложность и накладные расходы).
В моих приложениях длительные операции вызываются путем передачи ProgressTracker (который имеет два типа событий: процентное соотношение и текст состояния). Эта информация используется для обновления JProgressBar, JLabel, чего угодно ... Я также использую ProgressTracker, чтобы проверить, следует ли отменить операцию.
В SwingWorker есть код, который помогает объединить несколько обновлений, но он построен на предположении, что длительные задачи должны наследоваться от SwingWorker, что не помогает разделить проблемы. Вам действительно решать, в каком направлении двигаться - я лично предпочитаю, чтобы операции с моими данными не имели ничего общего с графическим интерфейсом.
Не забудьте публиковать свои обновления для любых компонентов Swing в EDT с помощью SwingUtilities.invokeLater ()