带线程的进度条(Java Swing)

带线程的进度条(Java Swing),java,swing,thread-sleep,Java,Swing,Thread Sleep,这里有一个小例子: private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { int x = 0; while (jProgressBar1.getValue() < 100) { try { Thread.sleep(50);

这里有一个小例子:

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());
        }
    }
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
int x=0;
while(jProgressBar1.getValue()<100){
试一试{
睡眠(50);
x++;
jProgressBar1.设定值(x);
jProgressBar1.repaint();
}捕获(中断异常例外){
Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE,null,ex);
}
System.out.println(jProgressBar1.getValue());
}
}

System.out.println(jProgressBar1.getValue())将数字返回到IDE输出,但jProgressBar1不绘制此值。这个代码怎么了?请帮忙

问题在于,您在执行“工作”(thread.sleep)的同一线程中调用了
.repaint()
。这意味着您正在安排一系列
repaint()
调用,但它们没有被处理。我还敢打赌,一旦值达到100,进度条就会跳到满状态,这是因为主线程已经结束,所有的
repaint()
调用最终都在处理中

为了使jProgressBars工作,您必须让它们的重新绘制发生在与您正在工作的线程不同的线程中(值得注意的是,它也应该在不同的线程中-对于大多数Swing更新也是如此)。在调用代码之前,请尝试在新线程中启动此Runnable:

public class ProgressBarPainter implements Runnable{
    public JProgressBar jProgressBar1;
    public void run(){
        while(true){
            try {
                Thread.sleep(50);
                jProgressBar1.repaint();
            } catch (InterruptedException ex) {
               break;
            }
        }
    }
}
示例使用上述功能的代码:

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;
            }
        }
    }
}
不要在Swing线程中使用Thread.sleep()。改用javax.swing.Timer

例如:

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

不管怎么说,没有它是不行的。。。我认为线程有问题。我用另一个代码测试了它:
intvalues[]={1,5,9,20,22,25,45,50,55,70,80,90,99100}
for(int-value:values){try{Thread.sleep(50);}catch(InterruptedException ex){Logger.getLogger(MainWindow.class.getName())..}`jProgressBar1.setValue(value);}}不使用
Thread.sleep()
因为它将冻结Swing应用程序。相反,您应该使用
javax.swing.Timer
。尝试使用
SwingWorker
我提供了一个示例,说明了它应该如何实现。是的,它可以工作,但它可以很快地填充progressbar。如何更改dalay?@alexkowalski这是计时器构造函数的第一个参数。将第二行更改为:final Timer t=new Timer(250,new ActionListener(){这没有帮助!不是1000不是10000…什么都没有发生,只是填充速度非常快而已。