Swing:按下 ESC 键时如何关闭对话框?

Posted

技术标签:

【中文标题】Swing:按下 ESC 键时如何关闭对话框?【英文标题】:Swing: how do I close a dialog when the ESC key is pressed? 【发布时间】:2010-10-13 04:15:25 【问题描述】:

使用 Swing 进行 GUI 开发。

我有一个自定义对话框,用于选择要在我的应用程序中打开的文件;它的类扩展了javax.swing.JDialog 并包含JFileChooser 以及其他组件,可以切换为显示或隐藏。

JFileChooser 组件已经自己处理了 ESC 键:当显示文件选择器(嵌入在我的对话框中)并且我按下 ESC 时,文件选择器会自行隐藏。

现在我希望我的对话框也这样做:当我按下 ESC 时,我希望对话框关闭。请注意,当显示嵌入式文件选择器时,ESC 键应该只隐藏它。

有什么想法吗?

【问题讨论】:

【参考方案1】:

使用InputMapActionMap 处理Swing 中的关键操作。要干净地关闭对话框,请向它发送一个窗口关闭事件。

来自我现在不复存在的博客:

private static final KeyStroke escapeStroke = 
    KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); 
public static final String dispatchWindowClosingActionMapKey = 
    "com.spodding.tackline.dispatch:WINDOW_CLOSING"; 
public static void installEscapeCloseOperation(final JDialog dialog)  
    Action dispatchClosing = new AbstractAction()  
        public void actionPerformed(ActionEvent event)  
            dialog.dispatchEvent(new WindowEvent( 
                dialog, WindowEvent.WINDOW_CLOSING 
            )); 
         
    ; 
    JRootPane root = dialog.getRootPane(); 
    root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( 
        escapeStroke, dispatchWindowClosingActionMapKey 
    ); 
    root.getActionMap().put( dispatchWindowClosingActionMapKey, dispatchClosing 
    ); 

【讨论】:

@Tom 你好,感谢你的精彩帖子,如果我在对话框中有任何文本库组件,你能否告诉我最佳实践。因为如果焦点在他们身上就行不通了。【参考方案2】:

这是我的,我也添加了 CtrlW 作为关闭快捷键

    Action closeAction = new AbstractAction()
        public void actionPerformed(ActionEvent e)
            dispose();
        
    ;

    KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0);
    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(esc, "closex");
    getRootPane().getActionMap().put("closex", closeAction);

    KeyStroke ctrlW = KeyStroke.getKeyStroke("control W");
    getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ctrlW, "close");
    getRootPane().getActionMap().put("close", closeAction); 

【讨论】:

【参考方案3】:

如果您正在寻找使用 Java 8 新功能的技术,请尝试使用 lambda 表达式:

dialog.getRootPane().registerKeyboardAction(e -> 
    window.dispose();
, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);

KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
int w = JComponent.WHEN_IN_FOCUSED_WINDOW;
dialog.getRootPane().registerKeyboardAction(e -> window.dispose(), k, w);

【讨论】:

【参考方案4】:

我在实现两个最佳答案时遇到了问题。这是一个相当紧凑的版本,使用AbstractAction 自动实现Action 的大部分方法,这些方法适用于基于文本的字段(根据@pratikabu 的要求):

final AbstractAction escapeAction = new AbstractAction() 
    private static final long serialVersionUID = 1L;

    @Override
    public void actionPerformed(ActionEvent ae) 
        dispose();
    
;

getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
        .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "ESCAPE_KEY");
getRootPane().getActionMap().put("ESCAPE_KEY", escapeAction);

参考文献

以上答案 http://www.coderanch.com/t/335357/GUI/java/KeyPressed-JDialog

【讨论】:

给别人的小记。我发现如果你不做escapeActionfinal,那么你会得到一个例外。我的 IDE 中没有显示它必须是 final。运行时出现异常。【参考方案5】:

你可以使用下面的sn-p。这更好,因为 rootPane 将从对话框中的任何组件获取事件。如果需要,可以将 setVisible(false) 替换为 dispose()。

public static void addEscapeListener(final JDialog dialog) 
    ActionListener escListener = new ActionListener() 

        @Override
        public void actionPerformed(ActionEvent e) 
            dialog.setVisible(false);
        
    ;

    dialog.getRootPane().registerKeyboardAction(escListener,
            KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
            JComponent.WHEN_IN_FOCUSED_WINDOW);


【讨论】:

听起来不错。我只是用一些代码替换 dialog.setVisible(false) 以实际取消对话框。我试试看。

以上是关于Swing:按下 ESC 键时如何关闭对话框?的主要内容,如果未能解决你的问题,请参考以下文章

在 GWT 中单击 ESCAPE(ESC) 时关闭对话框

如何防止在Enter和Escape键上关闭MFC对话框?

如何从 LWUIT 组件中处理对话框

当我按 Enter 键时,选项卡控件的选项卡页会关闭

Swing 对话框如何工作?

MFC 之 OnClose 与 OnCancel