在处理时更新JProgressBar

时间:2012-03-06 06:03:40

标签: java swing swingworker jprogressbar event-dispatch-thread

我知道这个问题已经在许多问题上被看到并且已经得到了解答,但是,我仍然无法通过它。

我只想更新progressBar,同时提取大型xml文件的一些东西。 我认为在不同的线程中使用耗时的循环已经足够了但是? 我设法得到的就是progressBar根本没有显示,或者在结束之前更新,就在它关闭之前。

在启动应用程序附近的某个地方,我有:

public class SomeClass {
    private SomeClass () {
        myXMLParser reader = new myXMLParser();
        CoolStuff fromXml = reader.readTheXml();
    }
}
使用JProgressBar显示和更新JDialog时

public class LoadingDialog extends JDialog {
    private JProgressBar progressBar;
    /* ... */
    public void progress() {
        progressBar.setValue(progressBar.getValue() + 1);
    }
}

所以我有这个 myXMLParser

public class myXMLParser {
    private LoadingDialog loadingDialog = new LoadingDialog();

    public CoolStuff readTheXml() {
        CoolStuff fromXml = new CoolStuff();
        while(manyIterations) {
            loadingDialog.progress();
            fromXml.add(some() + xml() + reading());
        }
        return fromXml;
    }
}

我见过SwingWorker的许多内容并使用PropertyChange个事件更新了progressBar,但是示例始终是 all-in-one ,其中包含处理和进度条在同一个类中,以及在类中的类,并且从Java开始,我无法将其转换为我的情况。

任何帮助?..任何(不太明显)的建议?

编辑:多亏了btantlinger,它的工作原理如下:

public class SomeClass {
    private SomeClass () {
        myXMLParser reader = new myXMLParser();
        new Thread(new Runnable() {
            @Override
            public void run() {
                CoolStuff fromXml = reader.readTheXml();
            }
        }).start();
    }
}

public class LoadingDialog extends JDialog {
    private JProgressBar progressBar;
    /* ... */
    public void progress() {
        progressBar.setValue(progressBar.getValue() + 1);
    }
}

public class myXMLParser {
    private LoadingDialog loadingDialog = new LoadingDialog();

    public CoolStuff readTheXml() {
        CoolStuff fromXml = new CoolStuff();
        while(manyIterations) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    loadingDialog.progress();
                }
            });
            fromXml.add(some() + xml() + reading());
        }
        return fromXml;
    }
}

2 个答案:

答案 0 :(得分:10)

您必须更新Swing Event Dispatch Thread上的JProgress栏。您无法在任何其他线程上修改Swing组件。

您唯一的另一种选择是在开始你的线程之前将JProgress栏设置为“indeterminate”,其中进度条将来回移动。

E.g

progBar.setIndeterminate(true);

请参阅SwingWorker javadoc: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

如果您不想使用SwingWorker,另一个选项是SwingUtilities.invokeLater方法

//inside your long running thread when you want to update a Swing component
SwingUtilities.invokeLater(new Runnable() {
    public void run() {

        //This will be called on the EDT
        progressBar.setValue(progressBar.getValue() + 1);


    }
});

答案 1 :(得分:0)

除了@btantlinger提供的代码之外,我在测试后发现它需要额外的代码行才能在处理时更新UI线程上的进度条。见下文。

-I