我希望JOptionPane出现在无模式对话框上方。例如,在以下应用中,请按JDialog
按钮以显示无模式对话框,然后按JOptionPane
按钮以显示JOptionPane确认对话框。不幸的是,JOptionPane出现在无模式对话框下。
在我的真实应用中,我有几个无模式的JDialogs,并且在多个不同的地方使用JOptionPane。
如何轻松使JOptionPane出现在所有无模JDialog实例之上? “轻松”是指在每个无模式JDialog结构或每个JOptionPane调用中添加1或2行。
我尝试的一种方法是使用JOptionPane的所有者制作一个始终处于顶部的新临时JFrame。这使JOptionPane位于顶部,但JOptionPane位于屏幕的中心,而不是原始JFrame的中心,我担心用户可能不会注意到它。
我尝试的另一种方法是在显示JOptionPane之前使所有无模式对话框不可见,然后再使其可见。但是,这种方式将所有对JOptionPane的调用都变得不容易,因为(我相信)它需要try-finally块才能可靠地执行。
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
public class App {
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(f, "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
答案 0 :(得分:2)
您需要为选项窗格设置正确的父项。要确定它,您可以使用所有打开的窗口的列表。在我的示例中,我使用了最后打开的窗口。
import java.awt.BorderLayout;
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.JOptionPane;
public class App {
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(findLatestWindow(), "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static Window findLatestWindow() {
Window result = null;
for (Window w : Window.getWindows()) {
if (w.isVisible()) {
result = w;
}
}
return result;
}
}
如果同时打开多个对话框,并且用户可以在这些对话框之间切换,则需要更多代码行。因为在您单击按钮后,框架始终是焦点所有者。
答案 1 :(得分:2)
在尝试了@Sergiy使用静态Window方法的想法之后,我想到了:
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class App {
static JFrame hideOwnedWindows(JFrame f) {
ArrayList<Window> arHidden = new ArrayList();
WindowAdapter wa = new WindowAdapter() {
@Override
public void windowActivated(WindowEvent e) {
for (Window w : arHidden)
w.setVisible(true);
f.removeWindowListener(this);
}
};
for (Window w : f.getOwnedWindows()) {
if (w.isVisible()) {
w.setVisible(false);
arHidden.add(w);
}
}
f.addWindowListener(wa);
return f;
}
public static void main(String[] args) {
JFrame f = new JFrame("App Frame");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog = new JButton("JDialog");
JButton btnOptionPane = new JButton("JOptionPane");
btnDialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog dlg = new JDialog(f, "Modeless Dialog", false);
dlg.setSize(256, 256);
dlg.setLocationRelativeTo(f);
dlg.setVisible(true);
}
});
btnOptionPane.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showConfirmDialog(hideOwnedWindows(f), "Confirm JOptionPane");
}
});
f.add(btnDialog, BorderLayout.WEST);
f.add(btnOptionPane, BorderLayout.EAST);
f.setSize(512, 512);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
“ hideOwnedWindows”方法将隐藏所有拥有的窗口(包括对话框),然后在下次激活主JFrame时将其还原。由于所有拥有的Windows在JOptionPane期间都是不可见的,我认为(希望)主JFrame始终在JOptionPane关闭时被激活。