2016-08-02 93 views
1

所以我有一個JTree將有不同數量的樹葉和節點,我需要在樹的葉子旁邊添加JComboBoxes,但沒有樹的其他部分。我嘗試過使用屏幕位置的葉子和邊界佈局來實現這一點,但盒子總是會結束,當我有很多葉子時,它們會變得非常糟糕,它們也似乎只是在框架中的1個位置上定位,並且隨着每個新的組合框持續吱吱作響添加。我怎麼可能實現我在找什麼?Jtrees和組合框佈局

回答

2

我需要添加旁向JComboBoxes樹的葉子,但樹

考慮創建自己的TreeCellRenderer直接集成了一個JComboBoxJTree的任何其他部分。爲了允許編輯JComboBox,您還需要實現一個處理編輯組件的TreeCellEditor以及編輯完成時該組件發生的操作。下面是放在一個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中的具體數據的自定義類的葉子旁邊JLabel一個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]; 
    } 

}