0

重複の可能性:
Java GUI JProgressBar が描画されない
メイン外のクラスでプログレス バーを使用できますか?

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

プログレスバーは表示されて実行されますが、プログレスバーの値が最後まで更新されると、私のアルゴリズムのみが実行されます。私は他の例を見ていますが、それがどのように機能するかはよくわかりません。

誰かが私がどこで間違ったのか教えてもらえますか?

4

1 に答える 1

4

Swing の最も重要な概念のいくつかは次のとおりです。

イベント ディスパッチ スレッド (ETD) 内で長時間実行/ブロック操作を実行しないでくださいこれにより、UI が「フリーズ」して応答しなくなります。何が素晴らしいかというと、あなたはこれを理解しているようです。

EDT 以外のスレッドから ui コンポーネントを作成または変更しないでくださいあなたはこれをしていません。

アクションの最善の原因は、を利用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;
            }
        }
    }
}

別の選択肢は a を使用するProgressMonitorか、本当に必死ならを使用することですSwingUtilities#invokeLater(Runnable)が、代わりに使用することをお勧めしますSwingWorker;)

于 2012-12-31T06:43:48.313 に答える