Jtrees和组合框布局

时间:2016-08-02 15:12:55

标签: java swing user-interface layout jtree

所以我有一个JTree,它将有不同数量的叶子和节点,我需要在树的叶子旁边添加JComboBoxes,但没有树的其他部分。我已经尝试使用叶子的屏幕位置和边框布局实现这一点,但是盒子总是最终关闭,当我有很多树叶时它会变得非常糟糕,它们似乎只是在框架中的1个位置进行本地化,并且每添加一个新的组合框就会让自己变得更加细腻。我怎么可能实现我正在寻找的东西?

1 个答案:

答案 0 :(得分:2)

  

我需要在树的叶子旁边添加JComboBoxes,但不需要树的其他部分

考虑创建自己的TreeCellRenderer,将JComboBox直接合并到JTree。为了允许编辑JComboBox,您还需要实现一个TreeCellEditor来处理编辑组件以及编辑完成后该组件发生的操作。以下是一个非常简单的示例,在JComboBox

的叶子中JLabel旁边放置JTree
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultTreeModel model = new DefaultTreeModel(root);
final JTree tree = new JTree(model);

//flyweight pattern components
//editor
final JComboBox editorComboBox = new JComboBox();
final JComboBox viewComboBox = new JComboBox();
final Box box = Box.createHorizontalBox();
final JLabel myLabel = new JLabel();
myLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 10));
box.add(myLabel);
box.add(Box.createHorizontalGlue());
box.add(viewComboBox);
//Custom Renderer
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer (){
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        if ( leaf ){
            if ( value instanceof MyLeafNode ){
                MyLeafNode node = (MyLeafNode)value;
                viewComboBox.removeAllItems();
                myLabel.setText(value.toString());
                for ( String item : node.items ){
                    viewComboBox.addItem(item);
                }
                viewComboBox.setSelectedItem(node.selected);
                return box;
            }
        }
        return this;
    }
};

//Custom Editor
final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, renderer){

    final ActionListener actionListener = new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            cancelCellEditing();
            tree.repaint();
        }
    };

    @Override
    public boolean isCellEditable(EventObject e){
        if ( e.getSource() instanceof JTree ){
            JTree tree = (JTree)e.getSource();
            if ( tree.getLastSelectedPathComponent() == null ){
                return false;
            }
            DefaultMutableTreeNode o = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
            return o.isLeaf();
        }
        return false;
    }

    @Override
    public void cancelCellEditing(){
        super.cancelCellEditing();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
        if ( node instanceof MyLeafNode) {
            String sel = editorComboBox.getSelectedItem().toString();
            MyLeafNode mln = (MyLeafNode)node;
            mln.selected = sel;
            editorComboBox.removeActionListener(actionListener);
            tree.repaint();
        }
    }

    @Override
    public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
        if ( leaf ){
            if ( tree.getLastSelectedPathComponent() instanceof MyLeafNode ){
                MyLeafNode o = (MyLeafNode)tree.getLastSelectedPathComponent();
                editorComboBox.removeAllItems();
                for ( String item : o.items ){
                    editorComboBox.addItem(item);
                }
                editorComboBox.setSelectedItem(o.selected);
                editorComboBox.addActionListener(actionListener);
            }
            return editorComboBox;

        }
        return super.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row);
    }

};
tree.setCellRenderer(renderer);
TreePath path = new TreePath(new TreeNode[]{root});
tree.expandPath(path);

for ( int i = 0; i < 2; i++ ){
    DefaultMutableTreeNode p = new DefaultMutableTreeNode("P" + i);
    model.insertNodeInto(p, root, i);
    for ( int j = 0; j < 2; j++ ){
        String[] items = {"Item 1", "Item 2", "Item 3", "Item 4"};
        MyLeafNode n = new MyLeafNode("N" + j, items);
        model.insertNodeInto(n, p, j);
    }
    path = new TreePath(new TreeNode[]{root, p});
    tree.expandPath(path);
}
tree.setCellEditor(editor);
tree.setEditable(true);

JScrollPane scroller = new JScrollPane(tree);
frame.add(scroller);
frame.pack();
frame.setVisible(true);

其中MyLeafNode是用于存储JComboBox特定数据的自定义类:

public class MyLeafNode extends DefaultMutableTreeNode{

    private String[] items;
    private String selected;

    public MyLeafNode(String name, String...items){
        super(name);
        this.items = items;
        this.selected = items[0];
    }

}