Что мешает моему индикатору выполнения обновиться?

Я пишу небольшую функцию, которая будет обновлять мой ProgressBar и базу JLabel на взвешенных случайных целых числах. Поток спит правильно, и случайные значения проходят, однако мой индикатор выполнения и jlabel не обновляются.

Это также оставляет мой графический интерфейс без ответа. Он не полностью блокирует мой графический интерфейс (я могу нажимать кнопки, но не выполняет функции, связанные с этими кнопками).

Бросок оператора печати в методе run() не распечатывается. Так что я думаю, что он никогда не попадет туда.

Вот мой метод до сих пор:

private void updateProgressBar(int max) {
    final int maxDiamonds = max;
    int i = 0;
    while(i <= max) {
        //get random obstacle found
        final Obstacle o = obstacle.next();
        System.out.println("Obstacle: " + o.getName());
        //get random number of diamonds for obstacle
        int numDiamonds = Integer.parseInt(numFoundDiamonds.next());
        System.out.println("Number of Diamonds: " + numDiamonds);
        //set currentValue for the progress bar
        final int currentValue = i;

        for(int j = o.getRemovalTime(); j >= 0; j--) {
            final int rSecs = j;
            System.out.println("Time remaining to remove: " + rSecs);
            try {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        progressBar.setString(currentValue + "/" + maxDiamonds);
                        statusLabel.setText("Found " + o.getName() + ". Removing: " + rSecs + " s Remaining.");
                    }
                });
                java.lang.Thread.sleep(1000);
            } catch (InterruptedException e) {
                JOptionPane.showMessageDialog(this, e.getMessage());
            }
        }
        i += numDiamonds;  
    }

}

Возможно, я упускаю из виду что-то простое.

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


person WilliamShatner    schedule 31.07.2013    source источник


Ответы (1)


Вы вызываете Thread.sleep(...) в потоке событий Swing, который переводит весь поток Swing и приложение в спящий режим. Используйте фоновый поток, такой как SwingWorker.

person Hovercraft Full Of Eels    schedule 31.07.2013
comment
Это заставляет поток спать до обновления индикатора выполнения и jlabel? - person WilliamShatner; 31.07.2013
comment
@WilliamShatner: да. Поток событий Swing приостанавливается до того, как очередь событий Swing успевает обработать помещенные в нее события. Опять же, используйте SwingWorker. Вот для чего это нужно. - person Hovercraft Full Of Eels; 31.07.2013
comment
Интересно, почему так много руководств показывают это так же, как мой метод выше. Думаю, я вернусь к тому, как вы показали мне это в первую очередь! stackoverflow .com/questions/10236995/ - person WilliamShatner; 31.07.2013
comment
@WilliamShatner: Точно. SwingWorker имеет состояние выполнения, которое может прослушивать PropertyChangeListener. Например, проверьте этот ответ. - person Hovercraft Full Of Eels; 31.07.2013
comment
Hovercraft, что меня беспокоит, так это то, что мне придется писать собственный класс всякий раз, когда я хочу правильно использовать JProgressBar. Если это правда, почему JProgressBar просто не расширяет SwingWorker по умолчанию? - person WilliamShatner; 31.07.2013
comment
@WilliamShatner: в этом прелесть ООП. Если вы хотите создать JProgressBar, связанный с SwingWorker, ничто не мешает вам создать этот класс самостоятельно. Я считаю, что предпочитаю разделять модель/представление/элемент управления. - person Hovercraft Full Of Eels; 31.07.2013