java - eventos - Swing: ¿cómo cierro un diálogo cuando se presiona la tecla ESC?
eventos de teclado en java netbeans (5)
Desarrollo de GUI con Swing.
Tengo un diálogo personalizado para elegir un archivo para abrir en mi aplicación; su clase extiende javax.swing.JDialog
y contiene, entre otros componentes, un JFileChooser
, que puede alternarse para mostrarse u ocultarse.
El componente JFileChooser
ya maneja la tecla ESC por sí mismo: cuando se muestra el selector de archivos (incrustado en mi cuadro de diálogo) y presiono ESC, el selector de archivos se oculta.
Ahora quisiera que mi diálogo hiciera lo mismo: cuando presiono ESC, quiero que se cierre el cuadro de diálogo. Eso sí, cuando se muestre el selector de archivos incrustado, la tecla ESC solo debería ocultarlo.
Algunas ideas ?
Aquí está el mío, agrego Ctrl W como cierre shorcut también
KeyStroke esc = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0);
Action closeAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
dispose();
}
};
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);
Puede usar el siguiente fragmento. Esto es mejor porque el Panel raíz obtendrá eventos de cualquier componente en el cuadro de diálogo. Puede reemplazar setVisible (false) con dispose () si lo desea.
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);
}
Si buscas una técnica que utilice las nuevas características de Java 8, prueba una expresión lambda:
dialog.getRootPane().registerKeyboardAction(e -> {
window.dispose();
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
o
KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
int w = JComponent.WHEN_IN_FOCUSED_WINDOW;
dialog.getRootPane().registerKeyboardAction(e -> window.dispose(), k, w);
Tuve problemas para implementar las dos respuestas principales. Esta es una versión bastante compacta que usa AbstractAction
para implementar automáticamente la mayoría de los métodos de Action
, que funciona en campos basados en texto (por solicitud 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);
Referencias
- las respuestas anteriores
- http://www.coderanch.com/t/335357/GUI/java/KeyPressed-JDialog
Use InputMap
y ActionMap
para manejar las acciones clave en Swing. Para cerrar el diálogo limpiamente, envíele un evento de cierre de ventana.
De mi 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
);
}