2011-01-31 10 views
4

JTreeにドラッグアンドドロップを実装しています。 私は、ユーザーがツリー内の異なるレベルにノードをドロップできるようにしたい。以下の例では異なるネストレベルでJTreeのノードをドロップする

、ユーザが「孫A2」と「子C」との項目を挿入していることを想像:

  1. 新しい孫を追加します。

    root 
        child A 
        grandchild A1 
        grandchild A2 
        child C 
        grandchild C1 
    

    は今、2つのオプションがあります。 「孫A」、または「孫A」になる

  2. 「子A」と「子B」の間に新しい「子B」を挿入します。

SWTでは、ノードを垂直方向に少し移動することで可能です。横線のインジケータは、ツリーノードがどのネストレベルに挿入されているかを示します。

スイングでこれはまったく可能ですか?私はこれに関する情報を見つけることができないようです。 Swingのラインインジケーターは常に1つのレベルでのみ表示されます。

もしそうでない場合は、回避策がありますか?

答えて

2

Swingのドラッグアンドドロップで作成した動作を正確に実行することはできません。

電位回避策は次のようにON_OR_INSERTためにあなたのドロップモードを設定することである。tree.setDropMode(DropMode.ON_OR_INSERT);

ON_OR_INSERT直接ノードまたはノード間のいずれかのドロップサポート。 INSERTパートは "A"と "B"の間のドロップをサポートしています。その後、ユーザーは二つの方法(あるいはその両方)のいずれかで、「A3」の後に「A」の新しい孫を追加できるようにすることができます:

  • 最後の子として項目を追加すると「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高さにすることはできませんが、(高さを低く、アイコンを非表示)、など)の外観を変更するためのカスタムレンダラを持っている場合があります。

関連する問題