如何在 Swing java 中制作 JFrame 模态

问题描述 投票:0回答:15

我创建了一个 GUI,其中使用了 JFrame。我应该如何使其成为模态?

java swing modal-dialog jframe
15个回答
77
投票

如果您想让窗口成为模态窗口,最好的选择是使用 JDialog 而不是 JFrame。查看有关 Java 6 中 Modality API 介绍的详细信息以获取信息。还有教程

这里有一些示例代码,它将在

JPanel panel
中显示
JDialog
,这是
Frame parentFrame
的模态。除了构造函数之外,这遵循与打开
JFrame
相同的模式。

final JDialog frame = new JDialog(parentFrame, frameTitle, true);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);

编辑:更新了 Modality API 链接并添加了教程链接(向 @spork 致敬)。


20
投票

您可以创建一个类,传递对父级

JFrame
的引用,并将其保存在
JFrame
变量中。然后您可以锁定创建新框架的框架。

parentFrame.disable();

//Some actions

parentFrame.enable();

12
投票

只需在课堂上将

JFrame
替换为
JDialog

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

然后在构造函数中写入

setModal(true);

之后您将能够在 netbeans 中构建您的表单 并且形式变为模态


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

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


您的模式对话框正在等待...


4
投票

据我所知,JFrame不能做Modal模式。使用 JDialog 代替并调用

setModalityType(Dialog.ModalityType type)
将其设置为模态(或非模态)。


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 多桌面上成功使用了此功能并具有正确的行为。

这是一个很好的例子,说明了 local 类很少使用的功能。

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

0
投票

我在这种情况下所做的是,在我想要保持可见的主 jframe(例如,菜单框架)中,我取消选择属性窗口中的选项

focusableWindowState
,因此它将是
FALSE
。完成后,我调用的 jframe 不会失去焦点,直到我关闭它们。


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


0
投票

Hola como no puedo hacer un commentario en estos momentos voy a poner por aquí la mejora del post de Dreamspace President, bueno y que pasa si queremos abrir un Formulario modal abriendolo desde otro que ya es modal que fue abierto desde otro que no es modal , bueno aquí está la solución muy simple.

Este es elmismo cóidigo pero con unas lineas más.

public void showModalJFrame(final JFrame window, final Frame owner) {
    boolean ownerAlwayOnTop = false;
    
    if (window == null) {
        throw new IllegalArgumentException();
    }
    
    if(owner.isAlwaysOnTop() && owner != null){
        owner.setModalExclusionType(Dialog.ModalExclusionType.NO_EXCLUDE);
        owner.setAlwaysOnTop(false);
    }
    
    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();
            
            if(!owner.isAlwaysOnTop() && owner != null){
                owner.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
                owner.setAlwaysOnTop(true);
            }
            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);
}

Lo único que agregué fue

if(owner.isAlwaysOnTop() && owner != null){
        owner.setModalExclusionType(Dialog.ModalExclusionType.NO_EXCLUDE);
        owner.setAlwaysOnTop(false);
    }

y

if(!owner.isAlwaysOnTop() && owner != null){
                owner.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
                owner.setAlwaysOnTop(true);
            }

-1
投票

有一些代码可能会有所帮助:

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class ModalJFrame extends JFrame {

    Object currentWindow = this;

    public ModalJFrame() 
    {
        super();
        super.setTitle("Main JFrame");
        super.setSize(500, 500);
        super.setResizable(true);
        super.setLocationRelativeTo(null);

        JMenuBar menuBar = new JMenuBar();
        super.setJMenuBar(menuBar);

        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");

        menuBar.add(fileMenu);
        menuBar.add(editMenu);

        JMenuItem newAction = new JMenuItem("New");
        JMenuItem openAction = new JMenuItem("Open");
        JMenuItem exitAction = new JMenuItem("Exit");
        JMenuItem cutAction = new JMenuItem("Cut");
        JMenuItem copyAction = new JMenuItem("Copy");
        JMenuItem pasteAction= new JMenuItem("Paste");

        fileMenu.add(newAction);
        fileMenu.add(openAction);
        fileMenu.addSeparator();
        fileMenu.add(exitAction);

        editMenu.add(cutAction);
        editMenu.add(copyAction);
        editMenu.addSeparator();
        editMenu.add(pasteAction);

        newAction.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent arg0)
            {

                JFrame popupJFrame = new JFrame();

                popupJFrame.addWindowListener(new WindowAdapter()
                {
                      public void windowClosing(WindowEvent e) 
                      {
                          ((Component) currentWindow).setEnabled(true);                     }
                      });

                ((Component) currentWindow).setEnabled(false);
                popupJFrame.setTitle("Pop up JFrame");
                popupJFrame.setSize(400, 500);
                popupJFrame.setAlwaysOnTop(true);
                popupJFrame.setResizable(false);
                popupJFrame.setLocationRelativeTo(getRootPane());
                popupJFrame.setVisible(true);
                popupJFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
            }
        });

        exitAction.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent arg0)
            {
                System.exit(0);
            }
        });
    }
    public static void main(String[] args) {

        ModalJFrame myWindow = new ModalJFrame();
        myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myWindow.setVisible(true);
    }
}

-2
投票

不确定你的JFrame的内容,如果你询问用户一些输入,你可以使用JOptionPane,这也可以将JFrame设置为模态

            JFrame frame = new JFrame();
            String bigList[] = new String[30];

            for (int i = 0; i < bigList.length; i++) {
              bigList[i] = Integer.toString(i);
            }

            JOptionPane.showInputDialog(
                    frame, 
                    "Select a item", 
                    "The List", 
                    JOptionPane.PLAIN_MESSAGE,
                    null,
                    bigList,
                    "none");
            }

-3
投票

最简单的方法是在可视化 JFrame 对象之前使用 pack() 方法。这是一个例子:

myFrame frm = new myFrame();
frm.pack();
frm.setVisible(true);
© www.soinside.com 2019 - 2024. All rights reserved.