4

我知道这个主题已经在很多问题上看到并得到了回答,但我仍然无法通过它。

我只想在提取大型 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事件来更新进度条的事情,但是示例始终是一体的,处理和进度条在同一个类中,以及类中的类,自从我开始使用 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;
    }
}
4

2 回答 2

10

您必须更新 Swing 事件调度线程上的 JProgress 栏。您不能在任何其他线程上修改 Swing 组件。

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

例如

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


    }
});
于 2012-03-06T06:10:51.317 回答
2

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

   SwingUtilities.invokeLater(new Runnable() {
       public void run() {
           progressBar.setValue((int)percentage);
           //below code to update progress bar while running on thread
           progressBar.update(progressBar.getGraphics());
       }
     });   
于 2017-11-08T02:25:14.100 回答