我的 JProgressBar 在 100% 之前不会更新



好的,我有以下代码。

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 时才显示。

我做错了什么?

谢谢!

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

考虑使用SwingWorker进行长时间的操作。如何使用进度条演示了SwingWorkerJProgressBar的用法。

确保从Event Dispatch Thread调用setValue方法。您可以使用SwingUtilities.invokeLater。阅读更多关于螺纹和摆动的信息。

请考虑以下简化示例:

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

问题是您在 EDT 中使用了一个更新进度的循环。在该循环退出之前,EDT 无法调度事件(如重绘、重新验证、调用稍后、鼠标事件、键事件等(,阻止它刷新进度栏。

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

供您参考,在 Java 中,方法和变量以小写字母开头。你的代码真的很难让其他人阅读。

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

好的,我已经尝试了以下教程,但我总是迷失在某个地方。 我需要的是一个创建并显示进度条(JProgressBar(的类,当我迭代从文件加载的数据并放入数据库内存时,我可以设置该进度条的值。 我的问题是,我找到的每个示例都有某种计数器填充进度条并从"main"函数执行。 每次我将该教程更改为我可以随意调用并显示栏的类时,我都不会显示栏(即框架出现,但栏甚至看起来都不像是在迭代完成后添加到框架中(。 我尝试使用SwingUtilities.invokeLater和SwingWorkers(下面上课的最新尝试(都有同样的问题。 更糟糕的是,我可以做一个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(保留教程并将主要内容更改为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();
    }
}

下面的代码片段更新正在进行的进度条

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

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

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

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

最新更新