5

わかりました、私は次のコードを持っています。

public class MyProgressBar extends JPanel implements MyData, Serializable {

    /**
     * 
     */

    public static final int MAX                = 10000;
    public static final int WIDTH              = 400;
    public static final int HEIGHT             = 75;

    private JProgressBar    MyBar              = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
    private JFrame          MyFrame            = new JFrame();

    private int             MyValue            = 0;

    private Thread          MyThread           = new Thread( new ProgressThread() );



    public MyProgressBar() {
        add(MyBar);

        int x = ( MyData.SCREEN.width  / 2 ) - ( WIDTH  / 2);
        int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);

        this.setBounds( x, y, WIDTH, HEIGHT );

        MyFrame.setBounds( x, y, WIDTH, HEIGHT );
        MyFrame.setUndecorated(true);
        MyFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
        MyFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
        MyFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
        MyFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
        MyFrame.setVisible(false);
        MyFrame.getContentPane().setLayout(null);

        MyBar.setStringPainted( true );
        MyBar.setBorderPainted( true );
        MyBar.setValue( 0 );
        MyBar.setBounds( 0, 0, WIDTH, HEIGHT );

        MyFrame.add( MyBar );
        MyFrame.pack();
        MyFrame.repaint();

    }

    public void MyUpdateBar() {
        MyBar.setValue( MyValue );
        MyBar.repaint();
        MyFrame.repaint();
        this.repaint();
        //dbug.Message( "MYPROGRESSBAR", "MyUpdateBar", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
    }

    public void MySetValue( int percent ) {
        MyValue = (int)( MAX * ( (double)percent / 100.0 ) );
        MyUpdateBar();
        //dbug.Message( "MYPROGRESSBAR", "MySetValue", "Value is %3.2f %d percent was %d", MyBar.getPercentComplete(), MyValue, percent );
    }

    public void CreateAndShow () {
        MyFrame.setVisible(true);
        MyThread.start();
    }

    public void HideAndClear () {
        MyThread.stop();
        //frame.setVisible(false);
    }

    class ProgressThread implements Runnable {
        public void run() {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    while( MyValue < MyBar.getMaximum() ) {
                        MyBar.setValue( MyValue );
                        MyBar.repaint();
                        MyFrame.repaint();
                        dbug.Message( "MYPROGRESSBAR", "THREAD", "Value is %3.2f %d", MyBar.getPercentComplete(), MyValue );
                    }
                }
            });
        }

    }



}

ご覧のとおり、進捗状況を表示したいクラスを作成しました。何が起こるかというと、クラスをインスタンス化します。XMLファイルをロードし、データを解析しているときに、dbugメッセージを出力させたときに表示されるMyValueを更新するように呼び出しています。ただし、バー自体は100%完了するまで表示されません。私は他の誰かの例をスレッド化して従うことについて読みました、そして私がそれを彼の例として残した場合、それはうまくいきました。いくつかの調整を行った場合(値を読み取るためにプログレスバーの設定値を設定するためにスレッドのループを変更する)、100になるまで表示されません。

私は何を間違えましたか?

ありがとう!

4

5 に答える 5

15

スレッドが実行されSwingUtilities.invokeLaterます。Swing で効果的に実行していますEvent Dispatch Thread。何を達成しようとしているのかわかりません。しかし、ブロックしているように見え、実行されていないためEDTwhileループは更新されMySetValueていません。

SwingWorker長時間の操作に使用することを検討してください。プログレス バーの使用方法SwingWorkerはwithの使用方法を示していJProgressBarます。

setValueからメソッドを呼び出すようにしてくださいEvent Dispatch Thread。そのために使えますSwingUtilities.invokeLaterThreads と Swingの詳細をお読みください。

次の単純化されたサンプルを検討してください。

public static void main(String[] arguments) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

    final JProgressBar bar = new JProgressBar(0, 100);

    Thread t = new Thread(){
        public void run(){
            for(int i = 0 ; i < 100 ; i++){
                final int percent = i;
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        bar.setValue(percent);
                    }
                  });

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {}
            }
        }
    };
    frame.add(bar);
    frame.pack();
    frame.setVisible(true);
    t.start();
}
于 2012-05-03T18:58:47.340 に答える
5

問題は、進行状況を更新する EDT でループを使用することです。そのループが終了するまで、EDT はイベント (再描画、再検証、invokeLater、マウス イベント、キー イベントなど) をディスパッチできず、プログレス バーが更新されません。

プログレス バーが更新されるたびに、EDT がそのイベントをディスパッチできるようにする方法を見つける必要があります。理想的には、「作業」をSwingWorkerを使用して EDT の外に移動し、その間にプログレスバーが EDT のプロパティ変更リスナーを介して更新されます。

参考までに、Java では、メソッドと変数は小文字で始まります。あなたのコードは、他の人にとって非常に読みにくいものです。

于 2012-05-03T19:10:11.200 に答える
1

それで、私はチュートリアルに従おうとしましたが、ここが私がいるところです。

わかりました、チュートリアルに従ってみましたが、どこかで迷子になります。必要なのは、プログレス バー (JProgressBar) を作成して表示するクラスです。ファイルからロードされたデータを反復処理してデータベース メモリに配置するときに値を設定できます。私の問題は、私が見つけたすべての例に、プログレスバーを埋めて「メイン」関数から実行するある種のカウンターがあることです。そのチュートリアルを自由に呼び出してバーを表示できるクラスに変更するたびに、バーが表示されません (つまり、フレームが表示されますが、バーは後でフレームに追加されたように見えません)。反復が行われます)。SwingUtilities.invokeLater と SwingWorker (以下のクラスでの最後の試み) を使用してみましたが、すべて同じ問題が発生しました。さらに悪いことに、dbug.myMessage を実行できます (基本的に System. out)、バーがメモリ内で変化していることを示すメッセージが表示されていないことを確認します。おそらく単純なものが明らかに欠けていますが、それが何であるかはわかりません。

ああ、もう 1 つ、チュートリアルをそのままにしておくと ( http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/ examples/components/ProgressBarDemo2Project/src/components/ProgressBarDemo2.java ) メインを createAndShow メソッドに変更するだけで動作しますが、もちろん必要なことは実行されません。

これについて別の質問を投稿しましたが、クラスを大幅に変更したため、新しい質問を投稿するのが最善だと思いました。

だから、ここに私の変更されたコードがありますが、動作していないようです:

public class MyProgressBar extends JPanel implements PropertyChangeListener, 
                                                     MyData, 
                                                     Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -1632492668549544408L;

    private MyDebug         dbug               = new MyDebug( MyData.MYDEBUGCHECK.MYPROGRESSBAR.getOn() );

    public static final int MAX                = 100;
    public static final int WIDTH              = 400;
    public static final int HEIGHT             = 75;

    private JProgressBar    myBar              = new JProgressBar( SwingConstants.HORIZONTAL, 0, MAX );
    private JFrame          myFrame            = new JFrame();

    public  Task            task;


    class Task extends SwingWorker<Void, Void> {

        public int myValue = 0;

        @Override
        public Void doInBackground() {
            //Initialize progress property.
            setProgress(0);
            while (myValue < 100) {
                //Make random progress.
                //myValue += random.nextInt(10);
                setProgress( Math.min( myValue, 100 ) );
                dbug.myMessage( "MYPROGRESSBAR", "doInBackground", "Value is %3.2f %d", myBar.getPercentComplete(), myValue );
                myBar.repaint();
            }
            return null;
        }

        public void done() {
        }

        public void mySetValue( int percent ) {
            myValue = (int)( MAX * ( (double)percent / 100.0 ) );
            dbug.myMessage( "MYPROGRESSBAR", "mySetValue", "Value is %3.2f %d percent was %d", myBar.getPercentComplete(), myValue, percent );
        }

    }



    public MyProgressBar() {
        add(myBar);

        int x = ( MyData.SCREEN.width  / 2 ) - ( WIDTH  / 2);
        int y = ( MyData.SCREEN.height / 2 ) - ( HEIGHT / 2);

        this.setBounds( x, y, WIDTH, HEIGHT );

        myFrame.setBounds( x, y, WIDTH, HEIGHT );
        myFrame.setUndecorated(true);
        myFrame.getContentPane().setSize( new Dimension( WIDTH, HEIGHT ) );
        myFrame.setMinimumSize( new Dimension( WIDTH, HEIGHT ) );
        myFrame.setPreferredSize( new Dimension( WIDTH, HEIGHT ) );
        myFrame.setSize( new Dimension( WIDTH, HEIGHT ) );
        myFrame.setVisible(false);
        myFrame.getContentPane().setLayout(null);
        myFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

        myBar.setStringPainted( true );
        myBar.setBorderPainted( true );
        myBar.setValue( 0 );
        myBar.setBounds( 0, 0, WIDTH, HEIGHT );
        myBar.addPropertyChangeListener( this );

        myFrame.add( myBar );

        //Create and set up the content pane.
        //JComponent newContentPane = new MyProgressBar();
        JComponent newContentPane = myBar;
        newContentPane.setOpaque(true);                     //content panes must be opaque

        myFrame.setContentPane(newContentPane);
        myFrame.pack();

    }

    public void createAndShow () {

        //Display the window.
        myFrame.setVisible(true);
        myFrame.repaint();

    }

    public void hideAndClear () {
        //myFrame.setVisible(false);
    }


    @Override
    public void propertyChange(PropertyChangeEvent args) {
        dbug.myMessage( "MYPROGRESSBAR", "propertyChange", "Value is %s", args.getPropertyName() );
        if ( "progress" == args.getPropertyName() ) {
            int progress = (Integer) args.getNewValue();
            //myBar.setValue(progress);
        }
    }

    public void start () {
        //Instances of javax.swing.SwingWorker are not reusuable, so
        //we create new instances as needed.
        task = new Task();
        task.addPropertyChangeListener(this);
        task.execute();
    }

}
于 2012-05-04T12:39:25.760 に答える
1

以下のスニペットは、進行中に進行状況バーを更新します

    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());}
         });   
于 2017-11-08T02:19:49.330 に答える