Swing: как закрыть диалог при нажатии клавиши ESC?
Разработка графического интерфейса с помощью Swing.
У меня есть настраиваемый диалог для выбора файла, который будет открыт в моем приложении; его класс расширяет javax.swing.JDialog
и содержит среди других компонентов a JFileChooser
, который можно переключать, чтобы отображаться или скрываться.
Компонент JFileChooser
уже сам обрабатывает клавишу ESC: когда отображается выбор файла (встроен в мой диалог), и я нажимаю ESC, файл выбирает сам.
Теперь я хотел бы, чтобы мой диалог делал то же самое: когда я нажимаю ESC, я хочу, чтобы диалог закрывался. Имейте в виду, что когда отображается встроенный выбор файла, ключ ESC должен скрывать его.
Любые идеи?
Ответы
Ответ 1
Используйте InputMap
и ActionMap
для работы с ключевыми действиями в Swing. Чтобы закрыть диалоговое окно, отправьте ему событие закрытия окна.
Из моего 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
);
}
Ответ 2
Вы можете использовать следующий фрагмент. Это лучше, потому что 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);
}
Ответ 3
Если вы ищете технику с использованием новых возможностей Java 8, попробуйте выражение лямбда:
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);
Ссылки
Ответ 5
Здесь мой, я добавляю управление + W как закрывающий shorcut, а
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);