在下面的示例中,模式对话框在事件调度线程中打开。由于对话框是模态的,因此方法setVisible()
在关闭之前不会返回。
有人可能会怀疑这会导致事件调度线程暂停,但这是错误的,因为按钮正在运行。
因此,setVisible()
方法不会阻塞该线程。
问题是:是否可以在不阻止程序的情况下显示模态对话框?
package tests.javax.swing;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Try_JDialog_Modality2 {
private static final Logger log = LoggerFactory.getLogger(Try_JDialog_Modality2.class);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
AbstractAction popupAction = new AbstractAction("popup") {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "popup");
}
};
JDialog dialog = new JDialog((JFrame)null, true);
dialog.setLayout(new FlowLayout());
dialog.add(new JButton(popupAction));
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
log.debug("After set visible");
}
});
}
}
更新
我可以使用以下代码段执行相同操作:
//dialog.setVisible(true);
new Thread(new Runnable() {
@Override
public void run() {
dialog.setVisible(true);
}
}).start();
log.debug("After set visible");
有更短的路吗?
答案 0 :(得分:3)
你的问题:
问题是:是否可以在不阻止程序的情况下显示模态对话框?
是的,在显示模态对话框之前调用方法。对于某些事情,最好使用回调类型的设置来完成,例如使用PropertyChangeListener或其他类型的侦听器。如果在可视化模态对话框之前设置并调用它,它应该可以工作。
至于问题的如何部分,我相信它会阻止对其他窗口的输入,但不会停止Swing事件线程。它确实可以通过调用SwingUtilities.invokeAndWait(...)
来停止来自调用代码的程序流。最好查看Swing源代码以获取详细信息。
修改强> 关于您的更新,从不执行此操作:
new Thread(new Runnable() {
@Override
public void run() {
dialog.setVisible(true);
}
}).start();
因为您现在保证启动Swing事件线程的关闭对话框。
答案 1 :(得分:0)
dialog.setVisible(true);
应在AWT Dispatcher线程上运行。所以你应该以其他方式做到。
public buttonPressed_OpenDialog_and_doTask(){
new Thread(new Runnable() {
@Override
public void run() {
/* my worker background task */
dialog.dispose(); // at the end of task call this
}
}).start();
dialog.setVisible(true);
// we will continue when worker thread finishes
}
请注意,即使您阻止AWT事件调度程序线程(通过方法setVisible())。 AWT事件调度程序线程仍然以某种方式运行 - 因此所有AWT通知都像往常一样工作。见doc dialog.setVisible()
请注意,即使后台任务要快,并且在前一个线程中调用dialog.dispose()
之前调用dialog.setVisible(true)
,一切都可以。幸运的是dialog.dispose()
礼貌地等待直到对话变得可见。