Обновление JProgressBar из новой темы - PullRequest
2 голосов
/ 28 апреля 2010

Как я могу обновить JProgressBar.setValue (int) из другого потока? Моя второстепенная цель - сделать это как можно меньше.

Вот код, который у меня сейчас есть:

// Part of the main class....
pp.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEvent event){
                new Thread(new Task(sd.getValue())).start(); 
            }
        });

public class Task implements Runnable {
    int val;
    public Task(int value){
        this.val = value;
    }

    @Override
    public void run() {
        for (int i = 0; i <= value; i++){ // Progressively increment variable i 
            pbar.setValue(i); // Set value 
            pbar.repaint(); // Refresh graphics 
            try{Thread.sleep(50);} // Sleep 50 milliseconds 
            catch (InterruptedException err){} 
        } 
    }
}

pp является JButton и запускает новый поток при нажатии JButton.

pbar - это объект JProgressBar из класса Main.

Как мне обновить его значение? (Прогресс)

Код выше в run () не может видеть pbar.

Ответы [ 3 ]

3 голосов
/ 28 апреля 2010

Всегда подчиняйся правилу свинга

После реализации компонента Swing весь код, который может влиять или зависеть от состояния этого компонента, должен выполняться в потоке диспетчеризации событий.

Что вы можете сделать, это создать наблюдателя, который будет обновлять ваш индикатор выполнения - такой как - в этом случае вы хотите показать ход загрузки данных по нажатию кнопки. Класс DemoHelper реализует Observable и отправляет обновления всем наблюдателям при загрузке определенного процента данных. Индикатор выполнения обновляется с помощью public void update(Observable o, Object arg) {

class PopulateAction implements ActionListener, Observer {

    JTable tableToRefresh;
    JProgressBar progressBar;
    JButton sourceButton;
    DemoHelper helper;
    public PopulateAction(JTable tableToRefresh, JProgressBar progressBarToUpdate) {
        this.tableToRefresh = tableToRefresh;
        this.progressBar = progressBarToUpdate;
    }

    public void actionPerformed(ActionEvent e) {
        helper = DemoHelper.getDemoHelper();
        helper.addObserver(this);
        sourceButton = ((JButton) e.getSource());
        sourceButton.setEnabled(false);
        helper.insertData();
    }

    public void update(Observable o, Object arg) {
        progressBar.setValue(helper.getPercentage());
    }
}

Бесстыдный плагин: это источник из моего демонстрационного проекта Не стесняйтесь просматривать для более подробной информации.

0 голосов
/ 28 апреля 2010
  • Нет необходимости явно вызывать pbra.repaint.
  • Обновление JProgressBar должно выполняться через поток рассылки GUI.

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        // Remember to make pbar final variable.
        pbar.setValue(i);
    }
});
0 голосов
/ 28 апреля 2010

Вы не должны делать какие-либо вещи Swing вне потока отправки событий. Чтобы получить доступ к этому, вам нужно создать Runnable с запущенным кодом и передать его SwingUtilities.invokeNow () или SwingUtilities.invokeLater (). Проблема в том, что нам нужна задержка в проверке вашего JProgressBar, чтобы избежать заклинивания потока Swing. Для этого нам понадобится таймер, который будет вызывать invokeNow или более позднюю версию в своем собственном Runnable. Посмотрите на http://www.javapractices.com/topic/TopicAction.do?Id=160 для более подробной информации.

...