Подождите, пока Swing завершит обновление JProgressBar, прежде чем продолжить - PullRequest
2 голосов
/ 02 октября 2011

У меня есть JFrame с CardLayout, установленным в качестве менеджера раскладки.Это имеет два JPanel подкласса в нем.Одним из них является панель WordsLoadingPanel, которая отображает текст «Загрузка слов ...» и имеет JProgressBar.Другой должен загрузить слова.Это занимает некоторое время (около 10-14 секунд для 100 слов; это довольно избирательный алгоритм), поэтому я хочу заверить пользователя, что программа все еще работает.Я заставил алгоритм загрузки в панели вызывать изменение свойства с firePropertyChange(String, int, int), и WordsLoadingPanel замечательно фиксирует это изменение - я знаю это, потому что я добавил прослушиватель для этого события для выполнения println, и он работает,Однако, когда я изменяю println на фактическое изменение значения JProgressBar, это ничего не делает.Я знаю, что я изменяю значение правильно, потому что, если я устанавливаю значение до запуска алгоритма, он работает, и , он работает на последней итерации цикла.Я предполагаю, что это потому, что мой алгоритм потребляет вычислительную мощность и не позволяет обновлять * 1013.

Итак, мой вопрос: как заставить мой алгоритм ждать Swing (будет ли этоAWT Dispatching Thread?) Чтобы завершить обновление индикатора выполнения, прежде чем продолжить?Я пытался:

  • Thread.yield в каждой итерации цикла
  • Thread.sleep(1000L) в каждой итерации цикла, в try / catch
  • помещая все в цикл в SwingUtilities.invokeLater(Runnable)
  • добавляя только процессорозатратный алгоритм в SwingUtilities.invokeLater(Runnable)

РЕДАКТИРОВАТЬ: Для дальнейшей поддержки моей гипотезы алгоритма использования ЦП(звучит как детская история…), когда я устанавливаю JProgressBar на неопределенный, он начинает двигаться только после , когда алгоритм завершает работу.

У кого-нибудь есть какие-либо предложения?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 02 октября 2011

Чтобы выполнять дорогостоящие операции в фоновом режиме, рассмотрите возможность использования класса SwingWorker.В документации есть примеры того, как использовать ее для выполнения задач, которые взаимодействуют с пользовательским интерфейсом в отдельном потоке, включая отображение прогресса в JProgressBar s.

Если у вас возникли проблемы с пониманием работы класса, подумайте:

  • SwingWorker - это универсальный класс, который принимает два параметра: T и V
  • Метод doInBackground возвращает T и выполняется в отдельномthread.
  • Поскольку Swing можно манипулировать только в потоке диспетчеризации событий, вы не можете манипулировать Swing в doInBackground.
  • Метод process принимает List<V> в качестве параметра ивызывается асинхронно в потоке диспетчеризации событий.
  • Метод publish принимает V... аргументов и отправляет их для обработки в методе process.

В заключение:

  • T - это тип результата вычисления, если он есть.
  • V - это тип данных, необходимых для управления пользовательским интерфейсом.
  • Ваш алгоритм должен работать полностью вdoInBackground.
  • Интерфейс пользователя должен обрабатываться методом process.
  • Ваш алгоритм должен использовать publish для отправки данных в метод process.
2 голосов
/ 02 октября 2011

ОК, я решил это. Для тех, у кого может быть похожая проблема, я решил изменить метод, с которого начинался алгоритм, с синхронного его выполнения на асинхронный (с new Thread(Runnable).start). Итак, мой код теперь

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        new Thread(new Runnable () {
            public void run () {
                window.keyboardTrainingPanel.initialize();                                  
            }
        }).start();
    }
});

Надеюсь, это кому-нибудь поможет! Однако, если есть лучший способ сделать это, не стесняйтесь сообщить мне.

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