首页 > 解决方案 > SwingWorker 的 done() 方法在处理 JDialog 时出现意外行为

问题描述

我有一个在远程数据库上执行查询的SwingWorker类。我为持有加载器动画的 JDialogdoInBackground调用publish(true)which 设置为 true。setVisible

一切都按预期正常工作:

  1. 后台方法启动。
  2. 显示了 JDialog 模式。
  3. 后台方法完成。
  4. JDialog 在done()方法中隐藏/处置。
  5. UI 使用数据库值进行更新。

但是,当我将我的应用程序指向在我的本地计算机上运行的数据库时,会显示 JDialog,但即使done()调用了它也不会关闭/处置。在我手动关闭加载程序对话框之前,这也会停止在 done 方法中执行 UI 代码。

这种奇怪的行为如下:

  1. 后台方法启动。
  2. 显示了 JDialog 模式。
  3. 后台方法完成。
  4. JDialog 不在方法中隐藏/处置done()
  5. 用户界面更新

我必须提到,在远程数据库上的执行需要 10 秒或更长时间,但在我的本地数据库上却是一瞬间。更快的速度如何导致这种奇怪的行为?

下面是我的代码片段:

    new SwingWorker<Void, Boolean>() {
        JDialog loader = new MyDialogLoader();

        @Override
        protected Void doInBackground() {
            publish(true);
    
            //DATABASE EXECUTION CODE IS HERE

            publish(false);
            return null;
        }

        @Override
        protected void process(List<Boolean> chunks) {
            for (Boolean val : chunks) {
                loader.setVisible(val);
            }
        }

        @Override
        protected void done() {
            loader.dispose();
            //UI UPDATE WITH DATABASE VALUES CODE HERE;
        }
    }.execute();

标签: javaswingswingworker

解决方案


可能有一个异常被抛出doBackground(),所以publish(false)没有被执行。可能是访问数据库时出错...

抛出的异常doBackgroundSwingWorker. 检查是否抛出此类异常的方法是在get()方法中调用done()方法。它将抛出一个ExecutionException具有原始异常的cause

    @Override
    protected void done() {
        loader.dispose();
        try {
            get();
        } catch (ExecutionException ex) {
            ex.printStackTrace();
            // some message or what ever using ex.getCause()
        } catch (InterruptedException ex) {
            ex.printStackTrace();
            // TODO
        }

        //UI UPDATE WITH DATABASE VALUES CODE HERE;
    }

推荐阅读