Отладка фокуса в Java
проблема:
я пытаюсь отладить некоторые проблемы, связанные с фокусом, в моем приложении Java Swing. Бывают моменты, когда некоторые компоненты, похоже, захватывают фокус, и я не могу понять, где в коде это происходит.
что я пробовал:
A
VetoableChangeListener
сKeyboardFocusManager
(дляfocusOwner
). Это дает мне информацию о том, какие компоненты теряют и получают фокус, но это не помогает мне определить, где в коде фокус просят.таможни
KeyboardFocusManager
. Но и в этом я могу вмешаться только тогда, когда он получает события. К этому времени стек вызовов вызоваrequestFocus
уже потеряли.таможни
EventQueue
. Но и там я могу вмешаться вdispatchEvent
метод, который снова вызывается из EDT. Снова стек вызовов теряется (интересно, чтоpostEvent(AWTEvent)
это не назвать).
вопрос:
что Я ищу стек вызовов, когда вызов requestFocusInWindow
сделано. Можно ли получить эту информацию. Возможно, если бы я мог переопределить метод, используемый для публикации события в EventQueue
, затем я могу распечатать дамп стека. Однако EventQueue.postEvent(AWTEvent)
не вызывается.
кто может предложить решение, которое поможет мне получить состояние стека при вызове requestFocus
или requestFocusInWIndow
может быть сделано?
2 ответов
кажется, они (Солнце) действительно не хотят, чтобы вы это делали. На первый взгляд, в этом пути нет виртуальных методов, которые можно легко переопределить, а не в EventQueue
(postEvent
используется только для invokeLater
и синтезирования событий из кода приложения), ни в KeyboardFocusManager
(как вы обнаружили, переопределяемые методы вызываются позже из цикла отправки.)
к счастью, если вы используете Sun JRE, там is место, куда вы можете вставить код, но это не красиво:
Component.requestFocus()
вызывает static KeyboardFocusManager.setMostRecentFocusOwner(Component)
, который обновляет частный static Map
под названием mostRecentFocusOwners
.
Итак, если вы можете получить доступ к этому static Map
используя отражение, вы можете заменить его на пересылку Map
что следы призывает его put
способ:
import com.google.common.collect.ForwardingMap;
// ...
Field mrfoField = KeyboardFocusManager.class.getDeclaredField("mostRecentFocusOwners");
mrfoField.setAccessible(true);
final Map delegate = (Map) mrfoField.get(null);
Map mrfo = new ForwardingMap() {
public Object put(Object key, Object value) {
new Throwable().printStackTrace();
return super.put(key, value);
}
protected Map delegate() {
return delegate;
}
};
mrfoField.set(null, mrfo);
и это будет ловить звонки на requestFocus
и дать вам трассировки стека.