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

时间:2019-06-04 07:40:16

标签: java swing

我希望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);
    }
}

JOptionPane showing under modeless JDialog

2 个答案:

答案 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关闭时被激活。