Как заставить кнопку глубоко во вложенной панели Swing получить фокус клавиатуры?

У меня есть поворотная рама, которая содержит встроенные панели, содержащие другие панели и т. д. В глубине есть кнопка. Я хочу, чтобы кнопка получила фокус, чтобы нажатие клавиши «ввод» генерировало событие actionPerformed.

Однако, если я делаю myButton.requestFocus() или myButton.requestFocusInWindow(), все окно получает фокус, но ничего не происходит с точки зрения клавиатуры.

Я явно что-то упускаю из подсистемы фокусировки.

Обновление 2: я явно добавил KeyListener в дополнение к ActionListener, и теперь он работает. Это действительно странно, так как я думал, что actionListener включает в себя как действия клавиш, так и действия мыши.


person Uri    schedule 09.07.2009    source источник
comment
Эта кнопка видна (например, не скрыта вложенной вкладкой или чем-то подобным)?   -  person akarnokd    schedule 10.07.2009
comment
Вы пробовали requestFocusInWindow()?   -  person Avrom    schedule 10.07.2009
comment
Да, я пробовал оба. И да, кнопка видна. Он находится внутри элемента управления с вкладками, но вкладка видна.   -  person Uri    schedule 10.07.2009


Ответы (6)


Чтобы клавиша ввода работала, вы, вероятно, захотите установить кнопку по умолчанию, а не фокус клавиатуры:

button.getRootPane().setDefaultButton(button);

Если вам действительно нужен фокус клавиатуры, ваша проблема может быть связана с вызовом requestFocus. Иногда, если он вызывается до того, как компонент станет полностью видимым, его можно проигнорировать. Чтобы исправить это, вы можете отложить вызов requestFocus до тех пор, пока не будут обработаны другие события:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        button.requestFocus();
    }
});
person Russ Hayward    schedule 09.07.2009

Похоже, что requestFocus() не работает на каком-то уровне. Попробуйте проверить, может ли какая-либо из родительских панелей jPanel или других компонентов запрашивать фокус, и пройдите свой путь, чтобы выяснить, в чем заключается проблема.

person sangretu    schedule 09.07.2009

Существует способ программно указать функциональность вкладки (вы знаете, когда вы нажимаете вкладку и выбирается следующий виджет)

По умолчанию он следует тому, как были добавлены компоненты.

Использование этого пользовательского механизма позволит вам выбрать вложенную кнопку в качестве первой, которая получит событие actionperformed.

К сожалению, я не помню, как называется этот «механизм», но это что-то вроде обхода или обхода фокуса.

person OscarRyz    schedule 09.07.2009
comment
Вы думаете о FocusTraversalPolicy: java.sun .com/j2se/1.5.0/docs/api/java/awt/ - person Joe Attardi; 27.07.2009

Во-первых, не используйте requestFocus(), используйте requestFocusInWindow(). У requestFocus есть проблемы, связанные с платформой, в то время как requestFocusInWindow более последователен.

Ваша актуальная проблема; компонент (или один из его родителей), вероятно, не виден или не может быть сфокусирован.

person Kevin Montrose    schedule 09.07.2009

Я хочу, чтобы кнопка получила фокус, чтобы нажатие клавиши «ввод» генерировало событие actionPerformed.

Это иждивенцы LAF. Enter работает в Windows, но не в Metal LAF. Подробнее см. Enter Key and Button. информация.

Метод requestFocusInWindow() работает, только если компонент в данный момент виден в кадре. Других трюков нет, поэтому мы просто делаем случайные предположения о том, что вы делаете неправильно. Если вам нужна дополнительная помощь, опубликуйте SSCCE, демонстрирующий проблему.

person camickr    schedule 09.07.2009

Вы можете получить rootPane фрейма и обновить inputMap и actionMap. См. приведенный ниже код.

Карта InputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ok");

ActionMap actionMap = getRootPane().getActionMap();
actionMap.put("ok", enterAction);

Здесь enterAction — это объект AbstractAction, действие которого actionPerformed() будет вызываться, когда пользователь нажимает Enter.

person Community    schedule 10.07.2009