简体   繁体   中英

Progress Bar with Thread (Java Swing)

Here is a little a example:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        int x = 0;
        while (jProgressBar1.getValue() < 100) {
            try {
                Thread.sleep(50);
                x++;
                jProgressBar1.setValue(x);
                jProgressBar1.repaint();
            } catch (InterruptedException ex) {
                Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
            System.out.println(jProgressBar1.getValue());
        }
    }

System.out.println(jProgressBar1.getValue()); returns digits to IDE output, but jProgressBar1 doesn't draw this value. What's wrong with this code? Please help.

Never use Thread.sleep() in Swing thread. Use javax.swing.Timer instead.

Example:

private void jButton1ActionPerformed(ActionEvent evt) {                                         
    final Timer t = new Timer(50, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            jProgressBar1.setValue(jProgressBar1.getValue() + 1);
            if (jProgressBar1.getValue() == 100) {
              ((Timer) e.getSource()).stop();
            }
        }
    });
    t.start();
}

The problem is that you're calling .repaint() in the same thread you're doing your "work" (Thread.sleep). "repaint() does not invoke paint() directly. It schedules a call to an intermediate method, update(). Finally, update() calls paint()..." . This means you're scheduling a bunch of repaint() calls, but they aren't being processed. I would also bet that once the value does reach 100 the progress bar jumps to being full, which is because the main thread has ended and all of the repaint() calls are finally being processed.

In order to make jProgressBars work, you have to have their repainting occur in a different thread than the one in which you are doing work (which notably should also be in a different thread - This is also true for most Swing updating). Try starting this Runnable in a new thread before you invoke your code:

public class ProgressBarPainter implements Runnable{
    public JProgressBar jProgressBar1;
    public void run(){
        while(true){
            try {
                Thread.sleep(50);
                jProgressBar1.repaint();
            } catch (InterruptedException ex) {
               break;
            }
        }
    }
}

Example functioning code to use the above:

public class Frame extends JFrame {

    private static final long serialVersionUID = 1L;
    private JProgressBar bar;

    public Frame(){
        JPanel contentPanel = (JPanel) getContentPane();

        JButton b = new JButton("Do Process");
        b.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                ProgressBarPainter p = new ProgressBarPainter();
                p.jProgressBar1 = bar; //Fill in with the bar you want painted
                Thread t = new Thread(p);
                t.start();

                Worker w = new Worker();
                w.jProgressBar1 = bar;
                Thread t2 = new Thread(w);
                t2.start();
            }

        });
        contentPanel.add(b, BorderLayout.SOUTH);

        bar = new JProgressBar();
        contentPanel.add(bar, BorderLayout.CENTER);

        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Frame();
    }

}

class Worker implements Runnable{
    public JProgressBar jProgressBar1;
    public void run(){
        int x = 0;
        while(jProgressBar1.getValue() != jProgressBar1.getMaximum()){
            try {
                //Do some work
                Thread.sleep(50);
                //Update bar
                jProgressBar1.setValue(x++);
            } catch (InterruptedException ex) {
               break;
            }
        }
    }
}

class ProgressBarPainter implements Runnable{
    public JProgressBar jProgressBar1;
    public void run(){
        while(true){
            try {
                Thread.sleep(50);
                jProgressBar1.repaint();
            } catch (InterruptedException ex) {
               break;
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM