Отладка фокуса в Java

Проблема:

Я пытаюсь отладить некоторые связанные с фокусом проблемы в своем Java приложение Swing. Существуют времена, когда некоторые компоненты, кажется, захватывают фокус, и я не могу выяснить, где в коде это происходит.

Что я попробовал:

  • A VetoableChangeListener с KeyboardFocusManager (для focusOwner). Это действительно дает мне информацию, о которой компоненты теряют и получают фокус, но это не помогает мне прикрепить точку, где в коде фокус требуют.

  • Пользовательское KeyboardFocusManager. Но в этом также я могу вмешаться только, когда это получает события. К тому времени стек вызовов вызова к requestFocus уже потерян.

  • Пользовательское EventQueue. Но там также я в состоянии вмешаться в dispatchEvent метод, который снова называют от EDT. Снова стек вызовов потерян (интересно postEvent(AWTEvent) не назван).

Вопрос:

То, что я ищу, является стеком вызовов когда вызов к requestFocusInWindow сделан. Действительно ли возможно получить эту информацию. Возможно, если я мог бы переопределить метод, используемый для регистрации события в EventQueue, тогда я могу распечатать дамп стека. Однако EventQueue.postEvent(AWTEvent) не становится вызванным.

Может любой предлагать решение, которое поможет мне получить состояние стека когда вызов к requestFocus или requestFocusInWIndow возможно, был сделан?

11
задан Michael Myers 8 February 2010 в 17:20
поделиться

1 ответ

Похоже, они (Солнце) действительно не хотят, чтобы вы этого делали. На первый взгляд кажется, что в этом пути нет никаких виртуальных методов, которые можно было бы легко переопределить, не в EventQueue ( postEvent используется только для invokeLater и синтезирование событий из кода приложения), ни в KeyboardFocusManager (как вы обнаружили, переопределяемые методы вызываются позже из цикла диспетчеризации).

К счастью, если вы используете Sun JRE, там - это место, куда можно вставить код, но это не очень красиво:

Component.requestFocus () вызывает статический KeyboardFocusManager.setMostRecentFocusOwner (Component) , который обновляет частный статический Карта называется mostRecentFocusOwners .

Итак, если вы можете получить доступ к этой статической карте с помощью отражения, вы можете заменить ее перенаправляющей картой , которая отслеживает вызовы его метода 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 и предоставит вам трассировку стека.

7
ответ дан 3 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: