Jtrees 和组合框布局

Jtrees and combobox layout

所以我有一个 JTree,它将有不同数量的叶子和节点,我需要在树的叶子旁边添加 JComboBoxes,但是 tree.I 的其他部分没有尝试使用屏幕位置叶子和边框布局来实现这个但是盒子总是结束,当我有很多叶子时它变得非常糟糕而且它们似乎也只是定位在框架中的 1 个位置并且随着每个新的组合框不断挤压自己更薄添加。我怎么可能实现我正在寻找的东西?

i need to add JComboBoxes next to the leaves of the tree but no other part of the tree

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

的叶子中将 JComboBox 放在 JLabel 旁边
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是自定义的class用于存储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];
    }

}