setModal在Jframe中有2个Jdialogs问题

当我设置我的第一个JDialog模态和第二个非模态时我遇到问题。

这是我试图实现的function:

  1. 点击“测试对话框!” 按钮,名为Custom Dialog MainJDialog将打开。
  2. 如果单击Custom Dialog Main中的 “yes”选项,将打开另一个名为Custom Dialog Search的 JDialog
  3. 如果在“ 自定义对话框搜索 ”中单击“是”选项,则自定义对话框位于前面。
  4. 我应该能够选择任何JDialog 。 例如,如果我选择自定义对话框搜索 ,则另一个对话框应该返回,反之亦然。

我面临的问题是当我在自定义对话框主菜单中单击“是”,然后在主对话框后面显示自定义对话框搜索

发生这种情况是因为我将自定义对话框搜索设置为非模态。 如果我这个对话框模式它正确显示但是在我点击“是”之后自定义对话框主要不在前面。

我甚至试图将CustomDialogSearch的父级设置为CustomDialog,但行为仍然不正确。

下面是我正在测试的示例代码。

 import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JButton; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.ActionEvent; import java.awt.Dimension; public class TestTheDialog implements ActionListener { JFrame mainFrame = null; JButton myButton = null; public TestTheDialog() { mainFrame = new JFrame("TestTheDialog Tester"); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); myButton = new JButton("Test the dialog!"); myButton.addActionListener(this); mainFrame.setLocationRelativeTo(null); mainFrame.getContentPane().add(myButton); mainFrame.pack(); mainFrame.setVisible(true); } public void actionPerformed(ActionEvent e) { if(myButton == e.getSource()) { System.err.println("Opening dialog."); CustomDialog myDialog = new CustomDialog(mainFrame, true, "Custom Dialog Main?"); System.err.println("After opening dialog."); if(myDialog.getAnswer()) { System.err.println("The answer stored in CustomDialog is 'true' (ie user clicked yes button.)"); } else { System.err.println("The answer stored in CustomDialog is 'false' (ie user clicked no button.)"); } } } public static void main(String argv[]) { TestTheDialog tester = new TestTheDialog(); } } import javax.swing.JDialog; import java.awt.event.ActionListener; import javax.swing.JPanel; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JButton; import java.awt.event.ActionEvent; public class CustomDialog extends JDialog implements ActionListener { private JPanel myPanel = null; private JButton yesButton = null; private JButton noButton = null; private boolean answer = false; private JFrame parentFrame; public boolean getAnswer() { return answer; } public CustomDialog(JFrame frame, boolean modal, String myMessage) { super(frame, modal); parentFrame = frame; myPanel = new JPanel(); getContentPane().add(myPanel); myPanel.add(new JLabel(myMessage)); yesButton = new JButton("Yes"); yesButton.addActionListener(this); myPanel.add(yesButton); noButton = new JButton("No"); noButton.addActionListener(this); myPanel.add(noButton); pack(); setLocationRelativeTo(frame); setVisible(true); } public void actionPerformed(ActionEvent e) { if(yesButton == e.getSource()) { CustomDialogSearch myDialog = new CustomDialogSearch(parentFrame, false, "CustomDialog Search?"); System.err.println("User chose yes."); answer = true; myDialog.getAnswer(); System.out.println("myDialog.getAnswer()="+myDialog.getAnswer()); myDialog.show(); if(myDialog.getAnswer()==true) { System.out.println("tofront"); this.toFront(); } //setVisible(false); } else if(noButton == e.getSource()) { System.err.println("User chose no."); answer = false; setVisible(false); } } } import javax.swing.JDialog; import java.awt.event.ActionListener; import javax.swing.JPanel; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JButton; import java.awt.event.ActionEvent; public class CustomDialogSearch extends JDialog implements ActionListener { private JPanel myPanel = null; private JButton yesButton = null; private JButton noButton = null; private boolean answer = false; public boolean getAnswer() { return answer; } public CustomDialogSearch(JFrame frame, boolean modal, String myMessage) { super(frame, modal); myPanel = new JPanel(); getContentPane().add(myPanel); myPanel.add(new JLabel(myMessage)); yesButton = new JButton("Yes"); yesButton.addActionListener(this); myPanel.add(yesButton); noButton = new JButton("No"); noButton.addActionListener(this); myPanel.add(noButton); pack(); setLocationRelativeTo(frame); setVisible(true); } public void actionPerformed(ActionEvent e) { if(yesButton == e.getSource()) { System.err.println("Search User chose yes."); answer = true; //setVisible(false); } else if(noButton == e.getSource()) { System.err.println("Search User chose no."); answer = false; setVisible(false); } } } 

我甚至试图将CustomDialogSearch的父级设置为CustomDialog,但行为仍然不正确。

我认为你在这里正确,但你需要使用对话框模态类型。 例如:

  • Custom Dialog Main (“父”对话框)的模态类型设置为Dialog.ModalityType.APPLICATION_MODAL 。 通过在此对话框可见时执行此操作,它将阻止除其子项之外的所有窗口。
  • 自定义对话框搜索的模态类型(“子”对话框)设置为Dialog.ModalityType.MODELESS 。 这样它就不会阻挡任何其他窗口,你可以从孩子到父母,反之亦然。

为了更好地理解,请参阅如何在对话框中使用模态文章。

以下是关于使用模态的代码示例,如上所述:

 import java.awt.Dialog; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class Demo { private void createAndShowGUI() { JButton button = new JButton("Create Parent modal dialog"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton)e.getSource(); JFrame owner = (JFrame)SwingUtilities.windowForComponent(button); Demo.this.createAndShowParentDialog(owner); } }); JFrame frame = new JFrame("Demo"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.getContentPane().add(button); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private void createAndShowParentDialog(JFrame owner) { JButton button = new JButton("Create Child non-modal dialog"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton)e.getSource(); JDialog parent = (JDialog)SwingUtilities.windowForComponent(button); Demo.this.createAndShowChildrenDialog(parent); } }); JDialog parentDialog = new JDialog(owner, "Parent dialog"); parentDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); parentDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); parentDialog.getContentPane().add(button); parentDialog.pack(); parentDialog.setLocationRelativeTo(null); parentDialog.setVisible(true); } private void createAndShowChildrenDialog(JDialog parent) { JButton backButton = new JButton("Back to parent dialog"); backButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton)e.getSource(); Window dialog = SwingUtilities.windowForComponent(button); dialog.getOwner().toFront(); } }); JDialog childDialog = new JDialog(parent, "Child dialog"); childDialog.setModalityType(Dialog.ModalityType.MODELESS); childDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); childDialog.getContentPane().add(backButton); childDialog.pack(); childDialog.setLocationRelativeTo(null); childDialog.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new Demo().createAndShowGUI(); } }); } } 

编辑

我可以选择父和子JDialogs的窗口,但是当我选择父JDialog窗口时,子JDialog仍然在父JDialog的前面。

那我现在对问题有了更好的了解。 此行为取决于本机窗口系统如何处理聚焦和活动窗口。 如果您调用例如toFront(),它会尝试将窗口放在堆栈的顶部但是有些平台不允许拥有其他窗口的窗口出现在它的childre之上。 调用toBack()方法时也会发生同样的情况。 有关更多详细信息,请参阅javadocs。

我已经在Windows 7上测试了我的代码(32位,如果它有任何区别)并且父对话框变得集中,但它的孩子仍然在顶部显示(没有聚焦)。 如上所述,窗口系统决定如何处理这个问题。