обновление JProgressBar во время обработки - PullRequest
4 голосов
/ 06 марта 2012

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

Я просто хочу обновить прогрессбар, извлекая некоторые вещи из большого XML-файла. Я думал, что этого было достаточно, чтобы иметь длительный цикл в другом потоке, но? .. Все, что мне удалось получить, - это индикатор выполнения, который либо вообще не показывался, либо обновлялся в конце незадолго до его закрытия.

Экземпляр где-то рядом с запуском приложения, у меня есть:

public class SomeClass {
    private SomeClass () {
        myXMLParser reader = new myXMLParser();
        CoolStuff fromXml = reader.readTheXml();
    }
}

при отображении и обновлении JDialog с JProgressBar:

public class LoadingDialog extends JDialog {
    private JProgressBar progressBar;
    /* ... */
    public void progress() {
        progressBar.setValue(progressBar.getValue() + 1);
    }
}

Итак, у меня есть myXMLParser :

public class myXMLParser {
    private LoadingDialog loadingDialog = new LoadingDialog();

    public CoolStuff readTheXml() {
        CoolStuff fromXml = new CoolStuff();
        while(manyIterations) {
            loadingDialog.progress();
            fromXml.add(some() + xml() + reading());
        }
        return fromXml;
    }
}

Я видел много вещей с SwingWorker и использованием событий PropertyChange, обновляющих progressBar, но примеры всегда даются all-in-one , с обработкой и индикатором выполнения в одном и том же классе, и с классами внутри классов, и так как я начинаю на Java, я не смог перевести это в мою ситуацию.

Любая помощь? .. Любые (не слишком очевидные) советы?

Редактировать: Так что благодаря btantlinger это сработало так:

public class SomeClass {
    private SomeClass () {
        myXMLParser reader = new myXMLParser();
        new Thread(new Runnable() {
            @Override
            public void run() {
                CoolStuff fromXml = reader.readTheXml();
            }
        }).start();
    }
}

public class LoadingDialog extends JDialog {
    private JProgressBar progressBar;
    /* ... */
    public void progress() {
        progressBar.setValue(progressBar.getValue() + 1);
    }
}

public class myXMLParser {
    private LoadingDialog loadingDialog = new LoadingDialog();

    public CoolStuff readTheXml() {
        CoolStuff fromXml = new CoolStuff();
        while(manyIterations) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    loadingDialog.progress();
                }
            });
            fromXml.add(some() + xml() + reading());
        }
        return fromXml;
    }
}

Ответы [ 2 ]

10 голосов
/ 06 марта 2012

Вы ДОЛЖНЫ обновить панель JProgress в потоке рассылки событий Swing. Вы не можете изменять компоненты Swing в любом другом потоке.

Ваша единственная альтернатива - установить полосу JProgress «неопределенная», прежде чем начинать поток, в котором индикатор выполнения будет просто перемещаться взад и вперед.

* 1005 например *

progBar.setIndeterminate(true);

См. Документацию SwingWorker: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

Если вы не хотите использовать SwingWorker, другой вариант - SwingUtilities.invokeLater метод

//inside your long running thread when you want to update a Swing component
SwingUtilities.invokeLater(new Runnable() {
    public void run() {

        //This will be called on the EDT
        progressBar.setValue(progressBar.getValue() + 1);


    }
});
0 голосов
/ 08 ноября 2017

В дополнение к коду, предоставленному @btantlinger, после тестирования я обнаружил, что требуется дополнительная строка кода для обновления индикатора выполнения в потоке пользовательского интерфейса при обработке.Смотри ниже.

   SwingUtilities.invokeLater(new Runnable() {
       public void run() {
       progressBar.setValue((int)percentage);
       //below code to update progress bar while running on thread
       progressBar.update(progressBar.getGraphics());}
     });   
...