【问题标题】:Problem making a JProgressBar update values in Loop (Threaded)在循环(线程)中制作 JProgressBar 更新值时出现问题
【发布时间】:2011-02-28 23:52:31
【问题描述】:

我试图让我的程序在执行某些操作时不断更新方法中的进度条值。然而,这直到最后才会发生,并且 UI 冻结。

在查看了与我的问题类似的问题后,我尝试实施已接受的解决方案(使用线程),但我无法使其正常工作。就像他们不在那里一样。

我的程序包含几个类,Main 是由 netbeans 在 JFrame Design 模式下自动创建的,所以有些东西,例如 static void mainpublic Main我不太确定它的某些内容。下面我会把这些方法的 sn-ps 和我的线程实现放在一起。

public class Main extends javax.swing.JFrame implements ActionListener, Runnable{
                                          // I added implements ActLis, Runn.....

...

static Main _this;      // I included this variable

...

public static void main(String args[]) {
        Main m = new Main();                               // Added by me
        new Thread(m).start();                             // Added by me
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Main().setVisible(true);
            }
        });
 }

...

public Main() {
        initComponents();
        _this = this;        // Added by me
}


...

// I also included these 2 methods in the class

public void actionPerformed(ActionEvent e) {                                    
    synchronized(this){                                                         
        notifyAll();                                                            
    }                                                                           
}                                                                               

public void run() {                                                             
    try{synchronized(this){wait();}}
    catch (InterruptedException e){}
    progressBar.setValue(50);                                                   
}

...

private void buttonPressed(java.awt.event.MouseEvent evt) {
   for(int i=0; i<=100; i++) {
      for(int j=0; j<=5; j++) {
         // does some work
      }
   run();
   }
}

我评论为I added...的所有东西都是我根据我在网上看到的教程和答案提出的,但似乎没有任何效果,感觉就像我尝试了近百万种不同的组合......

提前感谢您的帮助。

【问题讨论】:

    标签: java multithreading swing progress-bar swingworker


    【解决方案1】:

    这里有一些基础供您查看,如果您可以研究它并理解为什么每段代码都在那里,那么我认为它会有所帮助。随意在评论中提问(尽管我现在要睡觉了!)

    示例:

    public class ProgressBarDemo extends JFrame {
        private final JProgressBar progressBar = new JProgressBar(0, 100);
        private int progressCounter = 0;
    
        public ProgressBarDemo() {
            setContentPane(progressBar);
            setPreferredSize(new Dimension(100, 100));
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            pack();
            new Thread(new Runnable() {
                public void run() {
                    while (progressCounter <= 100) {
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                progressBar.setValue(progressCounter++);
                            }
                        });
                        try { Thread.sleep(500); } catch (InterruptedException e) {}
                    }
                }
            }).start();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new ProgressBarDemo().setVisible(true);
                }
            });
        }
    }
    

    解决问题的两种不同方法,改用 SwingWorker:

    SwingWorker 示例 1:

        ....
        public ProgressBarDemo() {
            setContentPane(progressBar);
            setPreferredSize(new Dimension(100, 100));
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            pack();
    
            SwingWorker<Integer, Void> worker = new SwingWorker<Integer,Void>() {
                public Integer doInBackground() {
                    while (progressCounter <= 100) {
                        setProgress(progressCounter++);
                        try { Thread.sleep(500); } catch (InterruptedException e) {}
                    }
                    return 0;
                }
            };
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent event) {
                    if ("progress".equals(event.getPropertyName())) {
                        progressBar.setValue((Integer)event.getNewValue());
                    }
                }
            });
            worker.execute();
        }
        ....
    

    SwingWorker 示例 2(不是很好,但很有趣):

        ....
        public ProgressBarDemo() {
            setContentPane(progressBar);
            setPreferredSize(new Dimension(100, 100));
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            pack();
    
            new SwingWorker<Integer,Integer>() {
                public Integer doInBackground() { 
                    while (progressCounter <= 100) {
                        publish(progressCounter++);
                        try { Thread.sleep(500); } catch (InterruptedException e) {}                    
                    }
                    return 0;
                }
                public void process(List<Integer> progresses) {
                    Integer maxProgress = null;
                    for (int progress : progresses) {
                        if (maxProgress == null || progress > maxProgress) {
                            maxProgress = progress;
                        }
                    }
                    progressBar.setValue(maxProgress);
                }
            }.execute();
        }
        ....
    

    【讨论】:

    • 哇,伙计,这对我来说一直意义重大,并认为您已经投入到帮助我理解线程和解决问题上。很高兴地说我已经设法使用您的第一个示例来做到这一点。我在哪里三重打勾作为最佳答案?
    【解决方案2】:

    您的代码有一些问题:(

    • 您创建了两次 Main,最终在一个实例上等待并通知另一个实例。
    • 您正在手动调用 run() 并安排一个线程来执行此操作...

    忘记教程,从头开始编写代码,只添加您理解的内容。

    【讨论】:

    • +1 iluxa 是对的。考虑SwingWorker,正如example 中所建议的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多