【问题标题】:Safely open and close modal JDialog (using SwingWorker)安全打开和关闭模态 JDialog(使用 SwingWorker)
【发布时间】:2012-10-19 07:46:59
【问题描述】:

我需要一种方法来从数据库中获取一些数据并防止用户在那一刻修改现有数据。

我创建了一个 SwingWorker 来更新数据库,并创建了一个模态 JDialog 来向用户显示正在发生的事情(使用 JProgressBar)。模态对话框的 defaultCloseOperation 设置为 DO_NOTHING,因此只能通过适当的调用关闭 - 我使用 setVisible(false)

MySwingWorkerTask myTask = new MySwingWorkerTask();
myTask.execute();
myModalDialog.setVisible(true);

SwingWorker 在 doInBackground() 中做了一些事情,最后它调用:

myModalDialog.setVisible(false);

我唯一关心和我的问题: SwingWorker 是否有可能在 worker 生成后的行中的 setVisible(true) 之前执行 setVisible(false)

如果是这样,setVisible(true) 可能会永远阻塞(用户无法关闭模式窗口)。

我是否必须实现以下内容:

while (!myModalDialog.isVisible()) {
    Thread.sleep(150);
}
myModalDialog.setVisible(false);

确保它真的会关闭?

【问题讨论】:

  • 您应该在done() 中调用myModalDialog.setVisible(false); 而不是doInBackground()。为什么不在execute 之前打电话给setVisible(true)
  • setVisible(true) 是一个阻塞调用
  • 哈哈 - 确实很好:-)
  • 如需尽快获得更好的帮助,请发帖SSCCE
  • 好的,我会再试一次。感谢 done() 提示。

标签: java multithreading swing jdialog swingworker


【解决方案1】:

一般来说,是的。

我要做的是在您的doInBackground 方法中使用SwingUtilities.invokeLater 显示对话框,并在您的done 方法中隐藏对话框。

这应该意味着即使对话框没有出现在屏幕上,您也可以对流程进行更多控制...

小问题是您现在必须将对话框传递给工作人员,以便它可以控制它...

public class TestSwingWorkerDialog {

    public static void main(String[] args) {
        new TestSwingWorkerDialog();
    }
    private JDialog dialog;

    public TestSwingWorkerDialog() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                MyWorker worker = new MyWorker();
                worker.execute();

            }
        });
    }

    public class MyWorker extends SwingWorker<Object, Object> {

        @Override
        protected Object doInBackground() throws Exception {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    getDialog().setVisible(true);
                }
            });
            Thread.sleep(2000);

            return null;
        }

        @Override
        protected void done() {
            System.out.println("now in done...");
            JDialog dialog = getDialog();
            // Don't care, dismiss the dialog
            dialog.setVisible(false);
        }

    }

    protected JDialog getDialog() {
        if (dialog == null) {

            dialog = new JDialog();
            dialog.setModal(true);
            dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
            dialog.setLayout(new BorderLayout());
            dialog.add(new JLabel("Please wait..."));
            dialog.setSize(200, 200);
            dialog.setLocationRelativeTo(null);

        }

        return dialog;
    }

}

【讨论】:

  • SwingUtilities.invokeLaterEventQueue.invokeLater 有什么区别?
  • 对不起,如果我的问题很愚蠢,但在您的示例中,是否可以保证,invokeLater 的运行方法肯定会在工作完成之前运行()?在我看来,我的帖子的主要问题仍然存在 - 理论上不确定的并发性,但我可能是错的。
  • @M.M.没有了。 SwingUtilities.invokeLater 将调用转发到 EventQueue.invokeLater。
  • @user1713059 这样做是为了保证 1. 只有在工作人员启动后才会打开对话框 2. 在工作完成之前不会关闭(或试图关闭) .因为 done 方法是在 EDT 的上下文中执行的,使用与我打开它类似的方法,所以 open 事件将在关闭之前执行,因为它首先添加到队列中。
  • @MadProgrammer 我在这里得到了准确的说明:stackoverflow.com/questions/6008279/swingutilities-invokelater/…
猜你喜欢
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-20
  • 2010-12-13
  • 1970-01-01
相关资源
最近更新 更多