简体   繁体   English

如何通过关闭JFrame直接关闭JOptionPane?

[英]How to close JOptionPane directly by closing JFrame?

I am new to learning javax.swing and have a doubt. 我是新来学习javax.swing ,对此有疑问。

I have a JFrame whose defaultCloseOperation is set to EXIT_ON_CLOSE . 我有一个JFramedefaultCloseOperation设置为EXIT_ON_CLOSE I have another component - a JOptionPane - over the JFrame . 我有另一个组成部分-一个JOptionPane - JFrame What I want to happen is that even when the focus is on the JOptionPane message dialog, I want the program to terminate when I click the x button on the JFrame window. 我想发生的是,即使焦点位于JOptionPane消息对话框上,我也希望在单击JFrame窗口上的x按钮时终止程序。

So, precisely, I'm looking to bring the JFrame in focus without dismissing the JOptionPane message dialog is over it so that I can close the JFrame window and, consequently, make the program terminate. 因此,恰恰是,我希望使JFrame成为焦点,而不会忽略其上方的JOptionPane消息对话框,以便我可以关闭JFrame窗口,并因此使程序终止。

Here is my code: 这是我的代码:

import javax.swing.*;

public class JJSS {
    public JFrame jf;

    public JJSS(){
        jf = new JFrame();

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setSize(400, 400);
        jf.setVisible(true);
    }

    public void runMethod(){
        String str = JOptionPane.showInputDialog(jf, "Enter something...");
        str = String.valueOf(new StringBuffer(str).reverse());
        JOptionPane.showMessageDialog(jf, "Reversed: "+str, "Output", JOptionPane.PLAIN_MESSAGE);
    }

    public static void main(String[] args){
        new JJSS().runMethod();
        System.exit(0);
    }

}

With the current code, nothing happens when I click on the close button ( x ) of the JFrame window. 使用当前代码,当我单击JFrame窗口的关闭按钮( x )时,什么也不会发生。

How do I bring the focus on the JFrame window, while the JOptionPane dialog is still on it, and terminate the program by closing the JFrame window? 如何在JOptionPane对话框仍在其上的同时将焦点放在JFrame窗口上,并通过关闭JFrame窗口来终止程序?

Dialog modality is the key 对话方式是关键

You can't do this with a normal JOptionPane or with any modal dialog as the modality prevents the user from interacting with other components of the GUI while the dialog is displayed. 您不能使用普通的JOptionPane或任何模式对话框来执行此操作,因为该模式会阻止用户在显示对话框时与GUI的其他组件进行交互。 You can only get this to work if you create a non-modal dialog, meaning that the JOptionPane must be created not with the JOptionPane static factory methods, but rather in a non-traditional way, using a JOptionPane constructor -- check the JOptionPane API for how to do this. 仅当创建非模式对话框时,此方法才能起作用,这意味着必须不使用JOptionPane静态工厂方法创建JOptionPane,而是使用JOptionPane构造函数以非传统方式创建-检查JOptionPane API有关如何执行此操作。

For example: 例如:

import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class NonModalJOptionPane {

    private static void createAndShowGui() {
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(400, 300));

        final JFrame frame = new JFrame("NonModalJOptionPane");

        panel.add(new JButton(new AbstractAction("Push Me") {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane optionPane = new JOptionPane("My Message", JOptionPane.PLAIN_MESSAGE);
                JDialog dialog = optionPane.createDialog(frame, "My Option");
                dialog.setModalityType(ModalityType.MODELESS); // **** key ***
                dialog.setVisible(true);
            }
        }));

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

The key to this code is here: 这段代码的关键在这里:

// create the JOptionPane using one of its constructors
JOptionPane optionPane = new JOptionPane("My Message", JOptionPane.PLAIN_MESSAGE);

// create a JDialog from it, tying it to the parent JFrame, here called "frame"
JDialog dialog = optionPane.createDialog(frame, "My Option");

// setting the modality type so that it is **not** modal
dialog.setModalityType(ModalityType.MODELESS); // **** key ***

// and then displaying it
dialog.setVisible(true);

Where I create a JOptionPane via its constructor, not via a static method, I create a JDialog and set it to be MODELESS , and then display it. 在我通过其构造函数而不是通过静态方法创建JOptionPane的地方,我创建了一个JDialog并将其设置为MODELESS ,然后显示它。


Another viable option is to create your own JDialog, making sure that you set it to being non-modal as well. 另一个可行的选择是创建自己的JDialog,并确保将其设置为非模态。

For example, you could add the following code to the code above: 例如,您可以将以下代码添加到上面的代码中:

panel.add(new JButton(new AbstractAction("Push Me 2 -- Using Dialog") {
    @Override
    public void actionPerformed(ActionEvent e) {
        // button that when pressed, closes the JDialog that holds it
        // similar to a JOptionPane's OK button
        JButton disposeWinBtn = new JButton(new DisposeWindowAction("OK", KeyEvent.VK_O));

        // create a bunch of JPanels, add components to them, ...
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(disposeWinBtn);

        JLabel msgLabel = new JLabel("My Message");
        JPanel msgPanel = new JPanel();
        msgPanel.add(msgLabel);

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(msgPanel, BorderLayout.CENTER);
        panel.add(bottomPanel, BorderLayout.PAGE_END);

        // create a JDialog whose parent component is the main JFrame
        // and make sure that it is *****non-modal ***** <===== this is KEY *****
        JDialog dialog = new JDialog(frame, "Dialog", ModalityType.MODELESS);
        dialog.add(panel);  // add the JPanel, panel, created above, with components
        dialog.pack();  // have layout managers do their thing
        dialog.setLocationRelativeTo(frame); // center it over the main JFrame
        dialog.setVisible(true);  // and display it
    }
}));

just under where the first button is added. 就在添加第一个按钮的位置。 You'll also need the DisposeWindowAction class, that allows the button to close and dispose of the window that is displaying it (here a JDialog window): 您还需要DisposeWindowAction类,该类允许按钮关闭并处理显示它的窗口(此处为JDialog窗口):

import java.awt.Component;
import java.awt.Window;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class DisposeWindowAction extends AbstractAction {
    public DisposeWindowAction(String name, int mnemonic) {
        super(name);
        putValue(MNEMONIC_KEY, mnemonic);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Component component = (Component) e.getSource();
        if (component == null) {
            return;
        }
        Window win = SwingUtilities.getWindowAncestor(component);
        if (win == null) {
            return;
        }
        win.dispose();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM