package components;import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ProgressBarTest {
    JFrame frame = new JFrame("JProgressBar");
    int showValue = 0;    public void start() {
        frame.setLayout(null);
        frame.setVisible(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JMenuBar mb = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem open = new JMenuItem("Open");
        open.addActionListener(new FileOpenListener());
        fileMenu.add(open);
        mb.add(fileMenu);
        frame.setBounds(100, 100, 600, 400);
        frame.setJMenuBar(mb);
        frame.setVisible(true);       // showValue = showFileChooser();
       // showProgress(showValue);    }    public static void main(String[] args) {
        ProgressBarTest test = new ProgressBarTest();
        test.start();
    }
    public void showProgress(int retValue) {
       // JFrame newFrame = new JFrame();
        JProgressBar bar = new JProgressBar(0, 100);
        bar.setBounds(100, 100, 400, 100);
        bar.setStringPainted(true);
//        newFrame.add(bar);
//        newFrame.pack();
//        newFrame.setVisible(true);
        frame.add(bar);
        if (retValue == JFileChooser.APPROVE_OPTION) {
            for (int i = 0; i < 101; i++) {
                bar.setValue(i);
                bar.setString("touming" + i);
                System.out.println("i = " + i);
//                newFrame.repaint();
                frame.repaint();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ee) {
                    ee.printStackTrace();
                }            }
        }
    }    public int showFileChooser() {
        JFileChooser chooser = new JFileChooser();
        chooser.setBounds(100, 100, 400, 300);
        frame.add(chooser);
        return chooser.showOpenDialog(frame);
    }    private class FileOpenListener implements ActionListener {        public void actionPerformed(ActionEvent e) {            showValue = showFileChooser();
            showProgress(showValue);
        }
    }
}这是源代码,在actionPerformed()里面progressbar就不能正确显示,如果在start()中把最后两句注释去掉,可以看到progressbar可以正确显示。请大虾们指点一下,如何才能在actionPerformed()里也能正确显示progressbar?

解决方案 »

  1.   

    有时需要从事件派发线程以外的线程中更新Swing组件,例如,在actionPerformed中有很费时的操作,需要很长时间才能返回,按钮激活后需要很长时间才能看到更新的列表,按钮会长时间保持按下的状态只到actionPerformed返回,一般说来耗时的操作不应该在事件处理方法中执行,因为事件处理返回之前,其他事件是不能触发的,界面类似于卡住的状况,所以在独立的线程上执行比较耗时的操作可能更好,这会立即更新用户界面和释放事件派发线程去派发其他的事件。public void actionPerformed(ActionEvent e) {     showValue = showFileChooser(); 
                
        new Thread() {
            public void run() {
                showProgress(showValue); 
            }
        }.start();
                
      

  2.   

    多谢dracularking,试了一下果然可以,还不知道怎么给分,是不是结贴的时候给,我来试一下。
      

  3.   

    还有一些概念The single-thread ruleHere's the rule:Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.This rule might sound scary, but for many simple programs, you don't have to worry about threads. Before we go into detail about how to write Swing code, let's define two terms: realized and event-dispatching thread.Realized means that the component's paint() method has been or might be called. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true), show(), or (this might surprise you) pack(). Once a window is realized, all components that it contains are realized. Another way to realize a component is to add it to a container that's already realized. You'll see examples of realizing components later.The event-dispatching thread is the thread that executes drawing and event-handling code. For example, the paint() and actionPerformed() methods are automatically executed in the event-dispatching thread. Another way to execute code in the event-dispatching thread is to use the SwingUtilities invokeLater() method.
    swing是单线程的,当初是基于为程序员简单地创建新组件考虑,无论是随手而写或者是扩展官方提供的组件
    但上文所述规则也是有例外的