问题描述
当我设置第一个 JDialog
模态和第二个非模态模式时,我遇到问题。
I am facing issues when I set my first JDialog
modal and the second one non-modal.
这是我试图实现的功能:
This is the functionality I am trying to implement:
- 点击测试对话框!按钮,
JDialog
,名称为自定义对话框
主将打开。 - 如果点击是自定义对话框主中的选项,另一个
JDialog
名为自定义对话搜索将打开。 - 如果在自定义对话框搜索中单击是选项,那么
自定义对话框主应该在前面。 - 我应该可以选择任何
JDialog
。例如,如果我选择
自定义对话框搜索,则另一个对话框应该返回
,反之亦然。
- On click of "Test the dialog!" button, a
JDialog
with name Custom DialogMain will open. - If click "yes" option in Custom Dialog Main, another
JDialog
named Custom Dialog Search will open. - If click "yes" option in Custom Dialog Search, thenCustom Dialog Main should come front.
- And I should be able to select any
JDialog
. For example if I selectCustom Dialog Search, the other dialog should goback and vice versa.
我面临的问题是当我在自定义对话框主中单击是时,主对话框后面会显示自定义对话框搜索。
Problem I am facing is when I click "yes" in Custom Dialog Main, then Custom Dialog Search is displayed behind the main dialog.
这种情况正在发生,因为我正在设置自定义对话框搜索非模态。
如果我这个对话框模式它正确显示但是在我点击是之后自定义对话框主不在前面。
This is happening because I am setting Custom Dialog Search non-modal.If I this dialog modal it is displayed correctly but after I click "yes" Custom Dialog Main doesn't come front.
我甚至试图将CustomDialogSearch的父级设置为CustomDialog,但行为仍然不正确。
I even tried to set CustomDialogSearch's parent to be CustomDialog the behaviour still not correct.
以下是我正在测试的示例代码。
Below is the example code I am testing.
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' (i.e. user clicked yes button.)");
}
else {
System.err.println("The answer stored in CustomDialog is 'false' (i.e. 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);
}
}
}
推荐答案
我认为你在这里正确,但你需要使用对话框模态类型。例如:
I think you're in the right track here but you need to play with dialogs modality type. For instance:
- 将自定义对话框主(父对话框)的模态类型设置为。通过执行此操作,当此对话框可见时,它将阻止除其子项之外的所有窗口。
- 将自定义对话框搜索(子对话框)的模态类型设置为 。这样它就不会阻挡任何其他窗口,你可以从孩子到父母,反之亦然。
- Set the modality type of Custom Dialog Main ("parent" dialog) as Dialog.ModalityType.APPLICATION_MODAL. By doing this when this dialog is visible it will block all windows except its children.
- Set the modality type of Custom Dialog Search ("child" dialog) as Dialog.ModalityType.MODELESS. This way it won't block any other window and you can go from the child to the parent and vice versa.
为了更好理解请参阅文章。
For a better understanding take a look to How to Use Modality in Dialogs article.
以下是关于使用模态的代码示例,如上所述:
Here is a code example about using modality as I've suggested above:
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();
}
});
}
}
编辑
Edit
我现在对问题有了更好的了解。此行为取决于本机窗口系统如何处理聚焦和活动窗口。如果你要求实例它会尝试将窗口放在堆栈的顶部但是某些平台不允许拥有其他窗口的窗口显示在其子列的顶部。当您致电方法。有关更多详细信息,请参阅javadoc。
Well I have a better understanding now on what is the problem. This behaviour depends on how native windowing system handles focused and active windows. Having said this if you call for instance toFront() it will attempt to place the window at the top of the stack BUT some platforms do not allow windows which own other windows to appear on top of its childre. The same happens when you call toBack() method. See the javadocs for more details.
我在Windows 7上测试了我的代码(32位,如果它有任何区别)并且父对话框变得有针对性但其子代仍然显示(没有专注)在顶部。如上所述,由窗口系统决定如何处理这个问题。
I've tested my code on Windows 7 (32 bits if it makes any difference) and parent dialog becomes focused but its children still showing (not focused) at the top. As mentioned above it's up to the windowing system decide how to handle this matter.
这篇关于setModal在Jframe中有2个Jdialogs问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!