【问题标题】:How to close JOptionPane directly by closing JFrame?如何通过关闭JFrame直接关闭JOptionPane?
【发布时间】:2017-08-26 10:48:54
【问题描述】:

我是学习javax.swing 的新手,并且有疑问。

我有一个JFrame,其defaultCloseOperation 设置为EXIT_ON_CLOSE。我还有另一个组件 - JOptionPane - over JFrame。我想要发生的是,即使焦点位于JOptionPane 消息对话框上,我也希望程序在我单击JFrame 窗口上的 x 按钮时终止。

因此,确切地说,我希望在不关闭 JOptionPane 消息对话框的情况下将 JFrame 聚焦,这样我就可以关闭 JFrame 窗口,从而使程序终止。

这是我的代码:

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

}

使用当前代码,当我单击 JFrame 窗口的关闭按钮 (x) 时,什么也没有发生。

如何将焦点放在 JFrame 窗口上,而 JOptionPane 对话框仍在其上,并通过关闭 JFrame 窗口来终止程序?

【问题讨论】:

  • 请查看编辑以回答,如果您有任何问题,请随时提问。

标签: java swing jframe joptionpane


【解决方案1】:

对话模式是关键

您不能使用普通的 JOptionPane 或任何模态对话框执行此操作,因为模态会阻止用户在显示对话框时与 GUI 的其他组件进行交互。如果您创建一个非模态对话框,您只能让它工作,这意味着 JOptionPane 必须不是使用 JOptionPane 静态工厂方法创建的,而是使用 JOptionPane 构造函数以非传统方式创建 - 检查@987654321 @ 了解如何执行此操作。

例如:

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

这段代码的关键在这里:

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

在我通过其构造函数而不是静态方法创建 JOptionPane 的地方,我创建了一个 JDialog 并将其设置为 MODELESS,然后显示它。 p>


另一个可行的选择是创建您自己的 JDialog,确保您也将其设置为非模态。

例如,您可以在上面的代码中添加以下代码:

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

就在添加第一个按钮的位置下方。您还需要 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();
    }
}

【讨论】:

  • @progyammer:请在此处查看Swing Tutorials 以及其他 Swing 资源:Swing Info,并询问您是否对答案有具体问题。
猜你喜欢
  • 1970-01-01
  • 2011-02-05
  • 2012-01-18
  • 2013-05-14
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
相关资源
最近更新 更多