3

我开发了一个用于创建和提取档案的 Java 应用程序,例如WinRAR。您可以使用多线程同时创建多个存档。最近,我想在每次创建时在新的 JFrame 中以 JProgressBar 的形式在归档创建期间添加信息状态。

但我的问题是在新的状态框架和创建档案的线程中生成信息。这就是我在存档线程中创建 JFrame 以更新当前进度条的原因。

但是就像我可以在不同的信息源和您的答案/评论中阅读它一样,它不利于 Java Swing和性能;我无法在EDT的其他地方创建摇摆对象。

但是,我应该如何解决我的问题?我怎样才能在我的归档文件的写入和它的状态 JFrame(使用 JProgressBar)之间建立通信?


编辑:

我实现了 SwingWorker 来管理我的应用程序中的 GUI。现在已经完成了,我还有一个问题:

使用 SwingWorker,我如何通过状态框架按钮上的事件来处理后台任务?(例如:暂停压缩或停止压缩。)

4

3 回答 3

5
  1. JDialog中放置并显示JProgressBar,不要创建新的Top-Level Container。创建一次并重复使用

  2. 长时间和繁重的代码会更好地重定向到后台任务

  3. 您可以JProgressBar从后台任务中移动

    • 仅当在 EDT 上完成 GUI 相关代码时,Swing 中的更多并发

    • 有两种正确的方法可以做到

      • 通过使用SwingWorker

      • fromRunnable#Thread但与 GUI 相关的代码必须包含在invokeLater()

于 2011-09-21T11:15:43.087 回答
5

正如其他人所建议的那样,最好的方法是使用SwingWorker.

SwingWorker属性是可侦听的,并且始终在 EDT 中调用侦听器,因此,您可以执行以下操作:

public class ArchivingWorker extends SwingWorker<Void, Void> {
    JProgressBar progressBar = null;
    // Other members here...
    ...

    public ArchivingWorker(...) {
        // Any specific initialization here (in EDT)
        addPropertyChangeListener(new PropertyChangeListener() {
            @Override void propertyChange(PropertyChangeEvent e) {
                if (    "state".equals(e.getPropertyName())
                    &&  e.getNewValue() == StateValue.STARTED) {
                    // Background thread has just started, show a progress dialog here
                    progressBar = new JProgressBar();
                    ...
                }
                else if ("progress".equals(e.getPropertyName())) {
                    // Update progress bar here with e.getNewValue()
                    ...
                }
            }
        });
    }

    @Override protected Void doInBackground() {
        // Archiving process here and update progress from time to time
        setProgress(progress);

        return null;
    }

    @Override protected void done() {
        // Ensure that archiving process worked correctly (no exception)
        try {
            get();
        } catch (Exception e) {
            // Handle exception (user feedback or whatever)
        } finally {
            // Close progress dialog
            ...
        }
    }
}

然后你可以ArchivingWorker根据需要使用它:

ArchivngWorker worker = new ArchivingWorker(...);
worker.execute();
于 2011-09-21T15:23:23.863 回答
1

@mKorbel提供的答案很好,但确实不需要使用另一个顶级容器(例如 a JDialog)来显示进度条。相反,您可以使用实例的Glass Pane 。JFrame

于 2011-09-21T12:02:17.467 回答