在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
的行为取决于模态?
答案 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 windows或dialog 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()。导致它没有阻塞。