Java 如何在无模式JDialog上显示JOptionPane

Java 如何在无模式JDialog上显示JOptionPane,java,swing,Java,Swing,我希望JOptionPane显示在非模态对话框上方。例如,在以下应用程序中,请按JDialog按钮以显示无模式对话框,然后按JOptionPane按钮以显示JOptionPane确认对话框。不幸的是,JOptionPane出现在无模式对话框下 在我真正的应用程序中,我有几个无模式的JDialogs,我在几个不同的地方使用JOptionPane 如何轻松地使JOptionPane显示在所有无模式JDialog实例之上? 我所说的“轻松”是指为每个无模式JDialog构造或每个JOptionPane

我希望JOptionPane显示在非模态对话框上方。例如,在以下应用程序中,请按
JDialog
按钮以显示无模式对话框,然后按
JOptionPane
按钮以显示JOptionPane确认对话框。不幸的是,JOptionPane出现在无模式对话框下

在我真正的应用程序中,我有几个无模式的JDialogs,我在几个不同的地方使用JOptionPane

如何轻松地使JOptionPane显示在所有无模式JDialog实例之上? 我所说的“轻松”是指为每个无模式JDialog构造或每个JOptionPane调用添加1或2行

我尝试的一种方法是制作一个新的临时无主JFrame,作为JOptionPane的所有者,它具有始终在顶部的选项。这使得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);
    }
}

您需要为选项窗格设置正确的父项。要确定它,您可以使用所有打开窗口的列表。在我的示例中,我使用上次打开的窗口

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;
    }
}

如果您同时打开了多个对话框,并且用户可以在这些对话框之间切换,那么您需要更多的代码行。因为在您的情况下,单击按钮后,框架始终是焦点所有者。

您需要为选项窗格设置正确的父项。要确定它,您可以使用所有打开窗口的列表。在我的示例中,我使用上次打开的窗口

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;
    }
}

如果您同时打开了多个对话框,并且用户可以在这些对话框之间切换,那么您需要更多的代码行。因为在你的例子中,点击按钮后,画面总是焦点的拥有者。

在尝试和试验了@Sergiy使用静态窗口方法的想法后,我想到了这个:

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);
    }

}
导入java.awt.BorderLayout;
导入java.awt.Window;
导入java.awt.event.*;
导入java.util.ArrayList;
导入javax.swing.*;
公共类应用程序{
静态JFrame HideOwnedWidows(JFrame f){
ArrayList arHidden=新建ArrayList();
WindowAdapter wa=新的WindowAdapter(){
@凌驾
公共无效窗口已激活(WindowEvent e){
用于(窗口w:arHidden)
w、 setVisible(真);
f、 移除WindowListener(此);
}
};
对于(窗口w:f.getOwnedWindows()){
如果(w.isVisible()){
w、 setVisible(假);
添加(w);
}
}
f、 addWindowListener(wa);
返回f;
}
公共静态void main(字符串[]args){
JFrame f=新JFrame(“应用程序框架”);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog=新JButton(“JDialog”);
JButton btnOptionPane=新JButton(“JOptionPane”);
addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件e){
JDialog dlg=newjdialog(f,“无模式对话框”,false);
dlg.setSize(256256);
dlg.相对位置(f);
dlg.setVisible(真);
}
});
btnOptionPane.addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件e){
showConfirmDialog(hideOwnedWindows(f),“确认JOptionPane”);
}
});
f、 添加(btnDialog,BorderLayout.WEST);
f、 添加(btnOptionPane,BorderLayout.EAST);
f、 设置大小(512、512);
f、 setLocationRelativeTo(空);
f、 setVisible(真);
}
}

“hideOwnedWindows”方法隐藏所有拥有的窗口,包括对话框,然后在下次激活主JFrame时恢复它们。由于所有拥有的窗口在JOptionPane期间都是不可见的,我认为(希望)当JOptionPane关闭时,主JFrame始终处于激活状态。

在尝试并试验了@Sergiy使用静态窗口方法的想法后,我想到了以下方法:

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);
    }

}
导入java.awt.BorderLayout;
导入java.awt.Window;
导入java.awt.event.*;
导入java.util.ArrayList;
导入javax.swing.*;
公共类应用程序{
静态JFrame HideOwnedWidows(JFrame f){
ArrayList arHidden=新建ArrayList();
WindowAdapter wa=新的WindowAdapter(){
@凌驾
公共无效窗口已激活(WindowEvent e){
用于(窗口w:arHidden)
w、 setVisible(真);
f、 移除WindowListener(此);
}
};
对于(窗口w:f.getOwnedWindows()){
如果(w.isVisible()){
w、 setVisible(假);
添加(w);
}
}
f、 addWindowListener(wa);
返回f;
}
公共静态void main(字符串[]args){
JFrame f=新JFrame(“应用程序框架”);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnDialog=新JButton(“JDialog”);
JButton btnOptionPane=新JButton(“JOptionPane”);
addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件e){
JDialog dlg=newjdialog(f,“无模式对话框”,false);
dlg.setSize(256256);
dlg.相对位置(f);
dlg.setVisible(真);
}
});
btnOptionPane.addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件e){
showConfirmDialog(hideOwnedWindows(f),“确认JOptionPane”);
}
});
f、 添加(btnDialog,BorderLayout.WEST