代码之家  ›  专栏  ›  技术社区  ›  obohovyk

带线程的进度条(Java Swing)

  •  1
  • obohovyk  · 技术社区  · 10 年前

    这里有一个小例子:

    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()); 返回IDE输出的数字,但jProgressBar1不绘制此值。这个代码有什么问题?请帮忙。

    2 回复  |  直到 10 年前
        1
  •  3
  •   Sergiy Medvynskyy    10 年前

    千万不要在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();
    }
    
        2
  •  -1
  •   Mshnik    10 年前

    问题是你在打电话 .repaint() 在同一个线程中,你正在做你的“工作”(thread.sleep)。 "repaint() does not invoke paint() directly. It schedules a call to an intermediate method, update(). Finally, update() calls paint()..." 。这意味着你正在安排一堆 repaint() 呼叫,但它们未被处理。我还打赌,一旦值达到100,进度条就会跳到满,这是因为主线程已经结束 重新绘制() 呼叫终于被处理了。

    为了使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;
                }
            }
        }
    }