2011-01-31 59 views
4

我正在實現拖放JTree中的一個。 我希望用戶能夠在樹中的不同級別放置一個節點。在不同的嵌套級別拖放JTree中的節點

在下面的例子中,假設用戶將「孫子A2」和「兒童C」之間的項目:

root 
    child A 
    grandchild A1 
    grandchild A2 
    child C 
    grandchild C1 

現在有兩個選擇:

  1. 附加一個新的外孫到「小孩A」,其將是「孫子A3」,或者
  2. 在「小孩A」和「小孩B」之間插入新的「小孩B」。

在SWT中,這可以通過在垂直方向上移動節點來實現。水平線指示符將顯示樹節點在哪個嵌套級別插入。

這在Swing中可能嗎?我似乎無法找到關於此的信息。 Swing中的線指示符始終僅顯示在一個級別。

如果不是,是否有解決方法?

回答

2

我不相信使用Swing的內置拖放功能可以完全實現您想要的行爲。

的潛在解決方法是設置你的下降模式ON_OR_INSERT如下:tree.setDropMode(DropMode.ON_OR_INSERT);

ON_OR_INSERT支持滴要麼直接或節點之間的節點。 INSERT部分支持在「A」和「B」之間下降。然後,您可以讓用戶在兩種方式(或兩者)一個加「A」,「A3」之後的一個新的外孫:

  • 解釋的下降直接在「A」爲加入該項目的最後一個子的「A」
  • 解釋一個節點上的壓降作爲節點之後加入的元素(這是有問題的,如果節點不是葉如預期的行爲是將元素添加作爲子)

如果您需要完全描述您所描述的行爲,那麼您可能需要爲表格編寫自定義DropTarget,並自己繪製所需的效果(顯示放置位置的行)。如果可能的話,我建議避免這種情況。

1

這是一個bug in the java drop location handling,如果不修改JDK源代碼就很難解決。它仍然沒有解決,但也有一個related enhancement request可能不切實際的解決方法,被關閉,因爲不會修復。

我一直能夠做到這一點的唯一方法是通過添加一個虛擬節點作爲任何容器節點的最後一個孩子。這很複雜,並增加了一行可能不合意的行,但允許用戶作爲容器節點的最後一個子節點。

public class TreeDragAndDrop { 
    private static final int CONTAINER_ROW = 0; 
    private static final int PLACEHOLDER_ROW = 3; 

    private JScrollPane getContent() { 
     JTree tree = new JTree(getTreeModel()) { 
      // Overridden to prevent placeholder selection via the keyboad 
      @Override 
      public void setSelectionInterval(int index0, int index1) { 
       int index = index0; 
       // Probably would use a better check for placeholder row in production 
       // and use a while loop in case the new index is also a placeholder 
       if (index == PLACEHOLDER_ROW) { 
        int currentSelection = getSelectionCount() > 0 ? getSelectionRows()[0] : -1; 
        if (currentSelection < index) { 
         index++; 
        } else { 
         index--; 
        } 
       } 
       super.setSelectionInterval(index, index); 
      } 

      // Overridden to prevent placeholder selection via the mouse 
      @Override 
      public void setSelectionPath(TreePath path) { 
       if (path != null && getRowForPath(path) != PLACEHOLDER_ROW) { 
        super.setSelectionPath(path); 
       } 
      } 
     }; 
     tree.setRootVisible(false); 
     tree.setDragEnabled(true); 
     tree.setDropMode(DropMode.INSERT); 
     tree.setTransferHandler(...); 
     tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 
     tree.expandRow(CONTAINER_ROW); 
     return new JScrollPane(tree); 
    } 

    protected static TreeModel getTreeModel() { 
     DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root"); 
     DefaultMutableTreeNode a; 

     a = new DefaultMutableTreeNode("A"); 
     root.add(a); 
     a.add(new DefaultMutableTreeNode("X")); 
     a.add(new DefaultMutableTreeNode("Y")); 
     a.add(new DefaultMutableTreeNode("")); // Placeholder node 

     root.add(new DefaultMutableTreeNode("B")); 
     root.add(new DefaultMutableTreeNode("C")); 
     return new DefaultTreeModel(root); 
    } 

    public static void main(String[] args) { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new TreeDragAndDrop().getContent()); 
     f.setSize(400, 400); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    // TransferHandler code omitted 
} 

您可能希望有一個自定義渲染改變佔位符行的樣子(例如隱藏圖標,降低高度(雖然你不能讓它高度爲0),等等)。