我的JProgressBar没有更新直到100%

时间:2012-05-03 18:52:38

标签: java swing swingworker runnable jprogressbar

好的,我有以下代码。

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文件,然后当我解析数据时,我正在调用更新MyValue,当我让我的dbug消息出来时,我会看到它。然而,酒吧本身甚至在100%完成之前都不显示。我已经阅读了关于线程和跟随别人的例子的内容,如果我把它作为他的例子就可以了。如果我做了一些调整(更改线程中的循环以填充进度条的setvalue以读取值),它甚至不会显示,直到它为100。

我做错了什么?

谢谢!

5 个答案:

答案 0 :(得分:14)

您的线程执行SwingUtilities.invokeLater。你实际上在Swing的Event Dispatch Thread上运行。不确定你想要达到什么目的。但看起来您阻止EDT并且while循环未更新,因为MySetValue未执行。

考虑使用SwingWorker进行冗长的操作。 How to Use Progress Bars演示了SwingWorkerJProgressBar的使用情况。

确保从setValue调用Event Dispatch Thread方法。您可以使用SwingUtilities.invokeLater。详细了解Threads and 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();
}

答案 1 :(得分:5)

问题是您在EDT中使用了一个更新进度的循环。在该循环退出之前,EDT无法调度事件(如重绘,重新验证,invokeLater,鼠标事件,键事件等等),从而无法刷新进度条。

您应该尝试找到让EDT在每次更新进度条之间调度事件的方法。理想情况下,您使用SwingWorker在EDT之外移动“工作”,同时通过EDT中的属性更改侦听器更新进度条。

为了您的信息,在Java中,方法和变量以小写字母开头。你的代码真的很难为别人阅读。

答案 2 :(得分:1)

所以,我试着按照教程进行操作,这就是我所处的位置。

好的,我已经尝试过以下教程,但我一直迷路。我需要的是一个创建和显示进度条(JProgressBar)的类,我可以设置值,因为我迭代从文件加载的数据并放入数据库内存。我遇到的问题是,我发现的每个例子都有某种计数器,它填充进度条并从“主”函数执行。每当我改变该教程成为一个我可以随意调用并显示条形的类时,我都没有显示条形图(即框架出现但是条形图甚至看起来都没有被添加到框架中,直到之后迭代完成)。我尝试过使用SwingUtilities.invokeLater和SwingWorker(下面的课程中的最新尝试)都有同样的问题。更糟糕的是,我可以做一个dbug.myMessage(基本上发送到System.out)并看到一条消息,显示该条正在更改内存中没有显示。我显然遗漏了一些可能很简单的东西,但我想不出它是什么。

哦,另外一件事,如果我按原样离开教程(http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/ProgressBarDemo2Project/src/components/ProgressBarDemo2.java)并将main更改为createAndShow方法,它可以正常工作,但当然它不会做我需要做的事情。< / p>

我确实发布了另一个关于此的问题,但我已经改变了这个课程,我认为最好发一个新问题。

所以,这是我改变的代码似乎不起作用:

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();
    }

}

答案 3 :(得分:1)

通过以下代码实现进度条的动态进度更新:

 int progress = Math.round(((float)finished/(float)(total)) * 100);
 uploadPrgressBar.setIndeterminate(progress == 0);
 uploadPrgressBar.setValue(progress);
 uploadPrgressBar.update(uploadPrgressBar.getGraphics());

在循环中调用包含上述代码的方法(代码逻辑),它将在每次迭代后动态更新进度条

答案 4 :(得分:0)

以下代码段会在进行中时更新进度条

    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());}
         });