Как заставить jprogressbar работать параллельно с моим алгоритмом

Возможный дубликат:
Java GUI JProgressBar не рисует
Можно ли использовать индикатор выполнения в классе вне main?

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

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {   

    final JProgressBar bar = new JProgressBar(0,250000);
    bar.setValue(1000);
    bar.setIndeterminate(false);
    JOptionPane jO = new JOptionPane(bar);

    Thread th = new Thread(){

    public void run(){
        for(int i = 1000 ; i < 250000 ; i+=10000){
           bar.setValue(i);
            try {
                Thread.sleep(100);
           } catch (InterruptedException e) {
            }
        }
    }
};
th.start();

final JDialog dialog = jO.createDialog(jO,"Experiment X");
dialog.pack();
dialog.setVisible(true);

//Algorithm goes here

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

Может кто-нибудь сказать мне, где я ошибся?

1 ответ

Некоторые из наиболее важных понятий в Swing:

НЕ выполняйте никаких длительных / блокирующих операций в потоке диспетчеризации событий (ETD). Это приведет к тому, что пользовательский интерфейс будет выглядеть "замороженным" и не реагирующим. Что приятно, вы, кажется, понимаете это.

НЕ создавайте и не изменяйте ЛЮБОЙ компонент пользовательского интерфейса из какого-либо потока ДРУГОГО, чем EDT Ты этого не делаешь.

Ваша лучшая причина действия состоит в том, чтобы воспользоваться SwingWorker Это позволяет вам выполнять длительные операции, одновременно обеспечивая обратную связь с слушателями.

public class TestProgress {

    public static void main(String[] args) {
        new TestProgress();
    }

    public TestProgress() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                ProgressPane progressPane = new ProgressPane();
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(progressPane);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

//                progressPane.doWork();
            }
        });
    }

    public class ProgressPane extends JPanel {

        private JProgressBar progressBar;
        private JButton startButton;

        public ProgressPane() {

            setLayout(new GridBagLayout());
            progressBar = new JProgressBar();

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(progressBar, gbc);
            startButton = new JButton("Start");
            gbc.gridy = 1;
            add(startButton, gbc);

            startButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    startButton.setEnabled(false);
                    doWork();
                }
            });

        }

        public void doWork() {

            Worker worker = new Worker();
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("progress".equals(evt.getPropertyName())) {
                        progressBar.setValue((Integer) evt.getNewValue());
                    }
                }
            });

            worker.execute();

        }

        public class Worker extends SwingWorker<Object, Object> {

            @Override
            protected void done() {
                startButton.setEnabled(true);
            }

            @Override
            protected Object doInBackground() throws Exception {

                for (int index = 0; index < 1000; index++) {
                    int progress = Math.round(((float) index / 1000f) * 100f);
                    setProgress(progress);

                    Thread.sleep(10);
                }

                return null;
            }
        }
    }
}

Вы другой выбор будет использовать ProgressMonitor или, если вы действительно в отчаянии, используйте SwingUtilities#invokeLater(Runnable), но я бы очень рекомендовал вам использовать SwingWorker вместо;)

Другие вопросы по тегам