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 文件,然后在我解析数据时,我调用更新 MyValue,当我让我的 dbug 消息出来时,我看到它。但是,在 100% 完成之前,栏本身甚至不会显示。我已经阅读了有关线程和遵循其他人的示例的信息,如果我将其作为他的示例,它就可以工作。如果我进行了一些调整(更改线程中的循环以填充进度条的设置值以读取值),它甚至不会显示,直到它为 100。

我做错什么了?

谢谢!

4

5 回答 5

15

你线程执行SwingUtilities.invokeLater。您正在有效地运行 Swing 的Event Dispatch Thread. 不知道你想达到什么目的。但看起来你正在阻塞EDT并且你的while循环没有更新,因为MySetValue没有执行。

考虑SwingWorker用于冗长的操作。如何使用进度条演示了SwingWorkerwith 的使用JProgressBar

确保setValueEvent Dispatch Thread. 你可以使用SwingUtilities.invokeLater它。阅读更多关于Threads 和 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) 并看到一条消息,显示该条在内存中发生变化,只是没有显示。我显然错过了一些可能很简单的东西,但我想不出它是什么。

哦,另一件事,如果我按原样离开本教程(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 方法,它就可以工作,但当然它不会做我需要它做的事情。

我确实发布了另一个关于此的问题,但是对课程进行了很大的改变,我认为最好发布一个新问题。

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

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 回答
1

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

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

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

于 2020-07-29T06:14:11.283 回答