如何在Swing Java中使JFrame成为模态窗口

70

我创建了一个GUI,在其中使用了JFrame。如何使它成为模态窗口?


14个回答

77
你最好使用 JDialog 而不是 JFrame,如果你想让窗口模态化。请查看 Java 6 中 Modality API 的介绍 以获取信息。还有一个教程
以下是一些示例代码,它将在一个对于 Frame parentFrame 模态的 JDialog 中显示一个JPanel panel。除了构造函数之外,这与打开 JFrame 的过程相同。
final JDialog frame = new JDialog(parentFrame, frameTitle, true);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);

编辑:更新了Modality API链接并添加了教程链接(感谢@spork的推荐)。


3
恐怕这似乎是唯一的解决方案。我正在对一些继承的代码进行同样的问题斗争。我有一个非常需要模态的JFrame。将所有内容转换为JDialog需要做很多丑陋的工作…… :-( - Brian Knoblauch
你能通过吗?创建一个不可见的模态JDialog,使其实例化JFrame,并在JFrame关闭时捕获必要的值并关闭JDialog。 - Redandwhite
2
链接已经失效 :( 但仍有人在尝试从中学习,这已经过去3年了!请尝试使用2013年的这个链接:http://docs.oracle.com/javase/tutorial/uiswing/misc/modality.html - Spork
更新了原始文章的链接并添加了Sporks教程链接 - 谢谢。 - akf
我觉得改用JDialog并不难看。这是一个很容易的更改。 - Erick Robertson

20

您可以创建一个类,该类接收对父JFrame的引用并将其保存在JFrame变量中。然后,您可以锁定创建新框架的框架。

parentFrame.disable();

//Some actions

parentFrame.enable();

很好,让我想到了一个循环来“挂起”(休眠)应用程序,同时帧是可见的,谢谢! - Aquarius Power
Kamil,Imgonzalves,你们能为我澄清一下吗?你们是说新的类应该在JDialog,JFrame或者创建OP主题JFrame的任何地方被创建吗? - Ed S

12

只需在类中将 JFrame 替换为 JDialog

public class MyDialog extends JFrame // delete JFrame and write JDialog

然后在构造函数中编写setModal(true);

之后,您将能够在NetBeans中构建表单并使其成为模态


1
不知道 setModal(true);.. 这太棒了。 - db2791
需要说明的是,这在NetBeans下不起作用,因为它的表单编辑器会将关闭对话设置为关闭操作,而在JDialog中是不允许的。 - Mohammed Housseyn Taleb

6
  1. 创建一个新的JPanel表单
  2. 添加你想要的组件和代码

YourJPanelForm stuff = new YourJPanelForm();
JOptionPane.showMessageDialog(null,stuff,"Your title here bro",JOptionPane.PLAIN_MESSAGE);

您的模态对话框已准备就绪...

哦,但是有一个确定按钮,我不想要。 - Daniel Katz
等等,仅仅将JPanel添加到JDialog中就可以了? - Zizouz212
这与jFrame无关。 - Jason K.

4

1

如果您准备使用 JDialog 而不是 JFrame,您可以将 ModalityType 设置为 APPLICATION_MODAL

这提供了与典型 JOptionPane 相同的行为:

import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;

public class MyDialog extends JFrame {

public MyDialog() {
    setBounds(300, 300, 300, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    setLayout(new FlowLayout());
    JButton btn = new JButton("TEST");
    add(btn);
    btn.addActionListener(new ActionListener() 
    {

        @Override
        public void actionPerformed(ActionEvent e) {
            showDialog();
        }
    });
}

private void showDialog() 
{

    JDialog dialog = new JDialog(this, Dialog.ModalityType.APPLICATION_MODAL);
    //OR, you can do the following...
    //JDialog dialog = new JDialog();
    //dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);

    dialog.setBounds(350, 350, 200, 200);
    dialog.setVisible(true);
}

public static void main(String[] args) 
{
    new MyDialog();
}
}

1
这个静态实用方法通过秘密地打开一个模态JDialog来显示一个模态JFrame。我在Windows 7、8和10多个桌面上成功地使用了这个方法,并且行为正确。
这是一个很好的例子,展示了很少使用的本地类特性。
import javax.swing.*;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

// ... (class declaration)

/**
 * Shows an already existing JFrame as if it were a modal JDialog. JFrames have the upside that they can be
 * maximized.
 * <p>
 * A hidden modal JDialog is "shown" to effect the modality.
 * <p>
 * When the JFrame is closed, this method's listener will pick up on that, close the modal JDialog, and remove the
 * listener.
 *
 * made by dreamspace-president.com
 *
 * @param window the JFrame to be shown
 * @param owner  the owner window (can be null)
 * @throws IllegalArgumentException if argument "window" is null
 */
public static void showModalJFrame(final JFrame window, final Frame owner) {

    if (window == null) {
        throw new IllegalArgumentException();
    }
    window.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
    window.setVisible(true);
    window.setAlwaysOnTop(true);

    final JDialog hiddenDialogForModality = new JDialog(owner, true);
    final class MyWindowCloseListener extends WindowAdapter {
        @Override
        public void windowClosed(final WindowEvent e) {
            window.dispose();
            hiddenDialogForModality.dispose();
        }
    }

    final MyWindowCloseListener myWindowCloseListener = new MyWindowCloseListener();
    window.addWindowListener(myWindowCloseListener);

    final Dimension smallSize = new Dimension(80, 80);
    hiddenDialogForModality.setMinimumSize(smallSize);
    hiddenDialogForModality.setSize(smallSize);
    hiddenDialogForModality.setMaximumSize(smallSize);
    hiddenDialogForModality.setLocation(-smallSize.width * 2, -smallSize.height * 2);
    hiddenDialogForModality.setVisible(true);
    window.removeWindowListener(myWindowCloseListener);
}

1

对我有效的唯一代码:

childFrame.setAlwaysOnTop(true);

在显示子/模态框之前,应在主/父框架上调用此代码。您的子/模态框也应该有这段代码:
parentFrame.setFocusableWindowState(false);
this.mainFrame.setEnabled(false);

1
以对话框模式显示任何框架的“简单”方法
public static void showFrameAsDialog(Component parentComponent, JFrame frame)
{
    try
    {
        JOptionPane pane = new JOptionPane(frame.getContentPane(), JOptionPane.PLAIN_MESSAGE,
                JOptionPane.NO_OPTION, null,
                new Object[]
                {
                }, null);

        pane.setComponentOrientation(((parentComponent == null)
                ? getRootFrame() : parentComponent).getComponentOrientation());

        int style = JRootPane.PLAIN_DIALOG;

        Method method = pane.getClass().getDeclaredMethod("createDialog", Component.class, String.class, int.class);
        method.setAccessible(true);
        Object objDialog = method.invoke(pane, parentComponent, frame.getTitle(), style);

        JDialog dialog = (JDialog) objDialog;
        if (frame.getWidth() > dialog.getWidth() || frame.getHeight() > dialog.getHeight())
        {
            dialog.setSize(frame.getWidth(), frame.getHeight());
            dialog.setLocationRelativeTo(parentComponent);
        }

        frame.addWindowListener(new java.awt.event.WindowAdapter()
        {
            @Override
            public void windowClosed(java.awt.event.WindowEvent windowEvent)
            {
                dialog.dispose();
            }
        });

        dialog.show();
        dialog.dispose();
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}

1
你的回答可以通过提供更多的支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到更多关于如何撰写好回答的信息。 - undefined
WTF?!但它有效。 - undefined

0

正如其他人提到的,您可以使用JDialog。如果您无法访问父框架或者想要冻结整个应用程序,只需将其设置为null:

final JDialog frame = new JDialog((JFrame)null, frameTitle, true); frame.setModal(true);
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接