Отладка фокуса в 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 и дать вам трассировки стека.