为什么我在编辑节点后失去JTree的短时间焦点?

时间:2011-02-17 15:39:43

标签: java swing focus jtree

尝试: F2 开始编辑, ENTER 停止编辑,焦点切换到下一个组件,然后以毫秒为单位返回树节点。在该示例中,您可以看到在JTabbedPane-Header中闪烁的focusPainted矩形。使用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 个答案:

答案 0 :(得分:2)

在编辑开始时,树将DefaultCellEditor添加到JTree层次结构。这个文本领域获得了关注。当编辑停止(按下Enter键)时,BasicTreeUI.completeEditing()方法检查树本身或编辑器组件是焦点所有者。在这种情况下,编辑完成后树将再次聚焦。

在停止算法中,编辑器将从树中删除。它之前是焦点所有者,因此焦点将转移到下一个可聚焦组件(焦点周期)。在您的UI中,这将是选项卡式窗格。

由于编辑器之前已经关注,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这是默认策略。

希望这有助于进一步发展。