web-dev-qa-db-fra.com

Swing: comment fermer une boîte de dialogue lorsque la touche ESC est enfoncée?

Développement GUI avec Swing.

J'ai une boîte de dialogue personnalisée pour choisir un fichier à ouvrir dans mon application; sa classe s'étend javax.swing.JDialog et contient, entre autres composants, un JFileChooser, qui peut être basculé pour être affiché ou masqué.

Le composant JFileChooser gère déjà la touche ESC par lui-même: lorsque le sélecteur de fichiers est affiché (intégré dans ma boîte de dialogue) et que j'appuie sur ÉCHAP, le sélecteur de fichiers se cache.

Maintenant, je voudrais que ma boîte de dialogue fasse de même: lorsque j'appuie sur ÉCHAP, je veux que la boîte de dialogue se ferme. Attention, lorsque le sélecteur de fichier incorporé est affiché, la touche ESC ne doit que le masquer.

Des idées ?

59
Leonel

Utilisez InputMap et ActionMap pour traiter les actions clés dans Swing. Pour fermer proprement la boîte de dialogue, envoyez-lui un événement de fermeture de fenêtre.

De mon weblog :

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

Vous pouvez utiliser l'extrait de code suivant. C'est mieux car le rootPane obtiendra les événements de n'importe quel composant de la boîte de dialogue. Vous pouvez remplacer setVisible (false) par dispose () si vous le souhaitez.

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

}
63
Ayman

Si vous cherchez une technique utilisant de nouvelles fonctionnalités de Java 8, essayez une expression lambda:

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

ou

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

J'ai eu des problèmes pour mettre en œuvre les deux meilleures réponses. Voici une version plutôt compacte utilisant AbstractAction pour implémenter automatiquement la plupart des méthodes de Action, qui fonctionne dans les champs textuels (selon la demande de @ 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);

Les références

4
skia.heliou

Voici le mien, j'ajoute CtrlW comme fermeture shorcut aswell

    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); 
2
Wesos de Queso