Почему я теряю фокус на короткое время от JTree после редактирования узла? - PullRequest
3 голосов
/ 17 февраля 2011

try: F2 начать редактирование и ENTER прекратить редактирование и фокус переключится на следующий компонент и вернется к древовидному узлу в миллисекундах. В примере вы можете видеть, как прямоугольник focusPainted мигает в заголовке JTabbedPane-Header. С FocusListener это должно быть яснее.

Почему я теряю фокус на короткое время от JTree после редактирования узла?

Как предотвратить это поведение?

public class Focus {

private static void createAndShowGUI() {
    final JTextArea text = new JTextArea("Tab Header gained focus");

    JTree tree = new JTree();
    tree.setEditable( true );
    int row = 0;
    while( row < tree.getRowCount() ) {
        tree.expandRow( row++ );
    }

    JTabbedPane tabp = new JTabbedPane();
    tabp.addTab( "Lorem", text );
    tabp.addFocusListener( new FocusListener() {
        @Override
        public void focusLost( FocusEvent e ) { }
        @Override
        public void focusGained( FocusEvent e ) {
            text.setText( text.getText() +"\nWoohoo, I got the focus!" );
        }
    });

    JFrame frame = new JFrame( "Focus" );
    frame.setLayout( new BorderLayout() );
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(tree, BorderLayout.WEST);
    frame.getContentPane().add(tabp, BorderLayout.CENTER);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    tree.startEditingAtPath( tree.getPathForRow( 0 ) );

}
public static void main(String[] x) {
    EventQueue.invokeLater(new Runnable() {
        @Override public void run() {
            createAndShowGUI();
        }
    });
}
}

1 Ответ

2 голосов
/ 17 февраля 2011

Дерево добавляет DefaultCellEditor в иерархию JTree при запуске редактирования.Это текстовое поле получает фокус.Когда редактирование остановлено (нажатие Enter), метод BasicTreeUI.completeEditing () проверяет, является ли само дерево или компонент редактора владельцем фокуса.В этом случае дерево будет снова сфокусировано после завершения редактирования.

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

Из-за того, что редактор был ранее сфокусирован, BasicTreeUI запрашивает фокус для дерева.

Эти шаги идеально соответствуют описанному вами поведению..

Единственное решение (не полное, но показывает направление) - установить собственный FocusTraversalPolicy:

private static class TreeEditorFocusTraversalPolicy extends DefaultFocusTraversalPolicy {
    private final JTree tree;
    public TreeEditorFocusTraversalPolicy(JTree tree) {
        this.tree = tree;
    }

    @Override
    public Component getComponentAfter(Container aContainer, Component aComponent) {
        if (aComponent instanceof CellEditor) {
            return tree;
        }
        return super.getComponentAfter(aContainer, aComponent); 
    }
}

Установить этот экземпляр на свое дерево:

tree.setFocusTraversalPolicy(new TreeEditorFocusTraversalPolicy(tree));
tree.setFocusCycleRoot(true);

Проблема до сих пор: обход фокуса (Tab, Shift + Tab) больше не работает.FocusTraversalPolicy - это огромная часть Swing, и ей нужно некоторое время, чтобы создать рабочую политику.Может быть, взгляните на LegacyGlueFocusTraversalPolicy, которая является политикой по умолчанию.

Надеюсь, это поможет продвинуться дальше.

...