如何制作setVisible块的非模态对话框?

时间:2011-08-01 07:17:57

标签: java swing dialog visibility blocking

在Swing(J)对话框中,setModal设置模态 - 即对话框是否应阻止对其他窗口的输入。然后,setVisible文档说用于模态对话框

  

如果对话框尚未显示,则在通过调用setVisible(false)或dispose隐藏对话框之前,此调用将不会返回。

实际上,如果对话框不是模态的,setVisible 会立即返回。示例代码:

JDialog jd = new JDialog();
jd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

/**
 * If set to false, setVisible returns right away.
 * If set to true, setVisible blocks until dialog is disposed.
 */
jd.setModal(false);

System.out.println("setting visible");
jd.setVisible(true);
System.out.println("set visible returned");

我想创建一个阻止输入到其他窗口的对话框,但仍然 阻止调用者。现在,当对话框不是模态时setVisible不会阻塞,有什么好办法呢?

是否有一些理由为什么 setVisible的行为取决于模态?

4 个答案:

答案 0 :(得分:5)

  

我需要创建一个不阻止对其他窗口输入的对话框,但会阻止调用者,以便我知道对话框何时关闭。

我通常不是通过阻止调用者来解决这个问题,而是通过使用某种类型的回调来解决这个问题 - 一个简单的界面,对话框在完成后调用。假设您的对话框有一个“确定”和“取消”按钮,您需要区分哪一个被按下。然后你可以做这样的事情:

public interface DialogCallback {
    void ok();
    void cancel();
}

public class MyModelessDialog extends JDialog {
    private final DialogCallback cbk;
    private JButton okButton, cancelButton;        

    public MyModelessDialog(DialogCallback callback) {
        cbk = callback;
        setModalityType(ModalityType.MODELESS);

        okButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onOK();
            }
        };

        cancelButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        };

        // Treat closing the dialog the same as pressing "Cancel":
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e)  {
                onCancel();
            }
        };
    }

    private void onOK() {
        cbk.ok();
    }

    private void onCancel() {
        cbk.cancel();
    }
}

然后,您只需将DialogCallback的实例传递给构造函数:

MyModelessDialog dlg = new MyModelessDialog(new DialogCallback() {
    public void onOK() { 
        // react to OK
    }
    public void onCancel() { 
        // react to Cancel
    }
 });

修改

  

有什么理由说为什么setVisible的行为取决于模态?

嗯,这就是模态窗口应该如何工作,不是吗?模态窗口在显示时阻止当前工作流程,而非模态/无模式不应该。参见例如维基百科页面modal windowsdialog boxes

答案 1 :(得分:0)

只需放置this.setModal(true)但不在构造函数上设置父对话框:

MyDialog dlg = new JDialog();

this.setModal(true);

当你致电setVisible(true)时,它不会停止

答案 2 :(得分:0)

直接方法是:

JDialog dialog = new JDialog(owner, ModalityType.DOCUMENT_MODAL);

答案 3 :(得分:0)

我找到了另一种方法。在我的进度条的构造函数中,它扩展了javax.swing.JDialog,我添加了:

setModalityType(ModalityType.APPLICATION_MODAL);

然后我覆盖了setVisible方法:

@Override
public void setVisible(boolean b) {
    if (b) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                showProgress();
            }
        }).start();
    } else {
        super.setVisible(false);
    }
}

在run()中,您可以看到对showProgress()的调用。这只是:

public void showProgress() {
    super.setVisible(true);
}

这里发生的是JDialog块的setVisible()方法。所以我重写了它,并在一个线程中调用了JDialog的setVisible()。导致它没有阻塞。