在多任务应用程序中管理 GUI 和 EDT

发布于 2024-12-05 20:18:39 字数 716 浏览 1 评论 0 原文

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

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

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

但那么,我该如何解决我的问题呢?如何在存档的写入与其状态 JFrame(使用 JProgressBar)之间建立通信?


编辑:

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

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

I developed a Java application for creating and extracting an archive - like WinRAR. You can create several archives at the same time with multithreading. And recently, I wanted to add an information status during the archive creation in the form of JProgressBar in a new JFrame at every creation.

But my problem is generating information in the new status frame and the thread which create the archive. That's why I create the JFrame in the archive thread for updating the progress bar currently.

But like I could read it in a diverse information source and on your answers/comments, it's against Java Swing and performance; I can't create swing object elsewhere that the EDT.

But then, how should I solve my problem? How can I etablish communication between the writing of my archive and its status JFrame (with JProgressBar)?


EDIT:

I implemented SwingWorker to manage the GUI in my application. Now it's done, I have an other question:

With SwingWorker, how do I act on the background task with an event on status Frame's button? (Example: pause compression or stop it.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

音盲 2024-12-12 20:18:39

正如其他人所建议的,最好的方法是使用 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();

As suggested by others, the best way is to use SwingWorker.

SwingWorker properties are listenable and listeners are always called in the EDT, thus, you could do something like:

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
            ...
        }
    }
}

Then you can use ArchivingWorker as you need it:

ArchivngWorker worker = new ArchivingWorker(...);
worker.execute();
流云如水 2024-12-12 20:18:39
  1. JProgressBar "http://download.oracle.com/javase/tutorial/uiswing/components/dialog.html" rel="nofollow">JDialog,并且不要创建新的 顶级容器。创建一次并重复使用

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

  3. 您可以继续前进来自后台任务的 JProgressBar

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

    • 有两种正确的方法

      • 通过使用SwingWorker

      • 来自 Runnable#Thread,但 GUI 相关代码必须包装到 invokeLater()

  1. Put and display JProgressBar in a JDialog, and don't create a new Top-Level Container. Create that once and re-use that

  2. Long timed and heavy code would be better redirected to the BackGround Task

  3. You can move with progress in JProgressBar from a background task

    • only if GUI related code is done on EDT more Concurrency in Swing

    • and there are two correct ways to do it

      • by using SwingWorker

      • from Runnable#Thread but GUI rellated code must be wrapped into invokeLater()

满栀 2024-12-12 20:18:39

@mKorbel 提供的答案很好,但实际上没有必要使用另一个顶级容器(例如JDialog)来显示进度条。相反,您可以使用JFrame 实例。

The answer provided by @mKorbel is fine, but there really is no need to use another top-level container (e.g. a JDialog) to display the progress bar. Instead, you can use the Glass Pane of the JFrame instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文