6

我有一个带有自定义 TreeModel 和自定义 TreeRenderer 的 JTree。树模型包含一堆不同类型的对象。其中一种类型的显示方式与其他类型不同: 显示的文本是对象的两个字段的串联。当我编辑单元格时,我想用编辑后的文本更新这些字段之一。到目前为止,我让它工作得很好。

我的问题:当编辑时显示的文本是 2 个字段的完整连接值时,即使您实际上只是在编辑其中一个字段,也会令人困惑。所以我只想在用户开始编辑时显示您正在编辑的一个字段的内容。

我试图用一个自定义的 CellEditor 来做到这一点,我看到了它应该工作的方式,在我的情况下,这种方法似乎有点矫枉过正。我只想在多种情况下更改显示的文本,所以我自然想实现它,而不是整个 CellEditor 用于我的 Tree 的全部内容。

有没有更快更简单的方法来做到这一点,还是我必须使用自定义编辑器?

谢谢

4

2 回答 2

9

没有办法绕过自定义编辑器,它是可能的最短解决方案:-) 此外,您需要在数据领域中使用一些方法来适当地解释编辑值并自行更新,例如自定义节点。

Fi(稍后会评论它,我在这台机器上的蹩脚的 Firefox 把我逼疯了)

/**
 * Basic code stolen from @trashgod at
* @see http://stackoverflow.com/a/11113648/230513
*/
public class TreeEditDemo extends JPanel {

    private JTree tree;
    private DefaultMutableTreeNode root;
    private DefaultTreeCellEditor editor;

    public TreeEditDemo() {
        super.setLayout(new GridLayout());
        root = new DefaultMutableTreeNode("Nodes");
        root.add(new MyResourceNode(new Resource("one", "first")));
        root.add(new MyResourceNode(new Resource("two", "first")));
        tree = new JTree(root);
        tree.setEditable(true);
        editor = new MyTreeCellEditor(tree,
            (DefaultTreeCellRenderer) tree.getCellRenderer());
        tree.setCellEditor(editor);
        this.add(new JScrollPane(tree));
    }

    private static class MyTreeCellEditor extends DefaultTreeCellEditor {

        public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
            super(tree, renderer);
        }

        @Override
        public Component getTreeCellEditorComponent(JTree tree, Object value,
                boolean isSelected, boolean expanded, boolean leaf, int row) {
            if (value instanceof MyResourceNode) {
                value = ((MyResourceNode) value).getName();
            }
            return super.getTreeCellEditorComponent(tree, value, isSelected, expanded,
                    leaf, row);
        }

        @Override
        public boolean isCellEditable(EventObject e) {
            return super.isCellEditable(e)
                && ((TreeNode) lastPath.getLastPathComponent()).isLeaf();
        }
    }

    public static class MyResourceNode extends DefaultMutableTreeNode {

        /**
         * @param resource
         */
        public MyResourceNode(Resource resource) {
            super(resource);
        }

        @Override
        public void setUserObject(Object userObject) {
            if (userObject instanceof String) {
                setName((String) userObject);
            } else if (userObject instanceof Resource) {
                super.setUserObject(userObject);
            }    
        }

        public void setName(String name) {
            if (getUserObject() != null) {
                getUserObject().setName(name);
            }
        }

        public String getName() {
            if (getUserObject() != null) {
                return getUserObject().getName();
            }
            return null;
        }

        @Override
        public Resource getUserObject() {
            return (Resource) super.getUserObject();
        }


    }
    private static class Resource {

        String name;
        private String category;

        public Resource(String name, String category) {
            this.name = name;
            this.category = category;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
        @Override
        public String toString() {
            // BEWARE: don't do this in production code!
            return name + " (" + category + ")";
        }
    }

    private void display() {
        JFrame f = new JFrame("TreeEditorDemo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TreeEditDemo().display();
            }
        });
    }
}
于 2012-09-29T10:37:23.980 回答
3

需要自定义编辑器。MyTreeCellEditor,如图所示显示了一种方法。它更新 a 的任意属性userObject,该属性被命名Resource并保存在 a 中DefaultMutableTreeNode。由于属性是文本,它也使用DefaultTreeCellRenderer. 您的自定义TreeModel可能管理一个类似userObject的,它是您的“不同类型的对象”的父级。

于 2012-09-28T17:46:42.037 回答