我正在使用 .js 檔案在 JTree 組件上實作拖放功能TransferHandler。我在 CodeRanch 上使用了這個舊執行緒,它幾乎是唯一一個明顯的資源,只要任何論壇上出現任何關于此的問題,就會被鏈接到。
我已經讓它與我的資料和 UI 配合得很好,因此可以輕松拖放葉節點。問題來了,當我嘗試拖動有孩子的節點時。覆寫布爾函式canImport(TransferSupport support)回傳 false,因為它檢查樹上的選定行。因此,我然后測驗了我是否可以CTRL Click在選擇我的拖動操作的“根”節點后手動選擇子節點,它作業得很好,并且節點,包括它的所有子節點都被拖放。
我的問題是:為了獲取選定的行,我呼叫tree.getSelectionRows()該值并將其保存到一個整數陣列中。如何將子行放入該整數陣列中?我知道我可能會重寫我的其他部分TransferHandler,但由于其他一切都很好,如果它實際上會按照我預期的方式選擇行,我覺得這是更簡單的方法。
uj5u.com熱心網友回復:
所以,拖放是……復雜的。您需要注意很多問題。
在鏈接的示例中,您應該注意它處理的是DefaultMutableTreeNodes 而不是TreeNodes,這可能不是問題,但您可能要記住這一點。
haveCompleteNode如果未選擇其子元素,似乎會阻止您移動分支節點……這對我來說似乎有些奇怪。
此外,它后面的代碼似乎阻止您將節點移動/復制到源節點當前級別以上的位置......出于某種原因
我也不確定我是否會保留所選節點的兩個副本,這是我,但防御性副本似乎有點過頭(可能是一個特殊的邊緣情況,但我會擔心樹是否可以在拖動操作期間更新,但那是我)。
那么,這里的教訓是什么?
你在網上找到的任何代碼都需要你花一些時間來真正弄清楚它在做什么。它可能剛開始非常適合您的需求,但在某個時間點,您將不得不卷起袖子深入研究以根據自己的需求對其進行修改。
您應該做的第一件事是充分了解拖放和資料傳輸API。
以下是您鏈接的代碼的修改示例,它允許您移動分支節點(及其子節點),并允許您將它們移動到其源深度“上方”的位置。
但同樣 - 您需要花時間了解代碼正在做什么并準備好根據您的需要對其進行修改
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import static javax.swing.TransferHandler.COPY_OR_MOVE;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class TreeDragAndDrop {
private JScrollPane getContent() {
JTree tree = new JTree();
tree.setDragEnabled(true);
tree.setDropMode(DropMode.ON_OR_INSERT);
tree.setTransferHandler(new TreeTransferHandler());
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
expandTree(tree);
return new JScrollPane(tree);
}
private void expandTree(JTree tree) {
DefaultMutableTreeNode root
= (DefaultMutableTreeNode) tree.getModel().getRoot();
Enumeration e = root.breadthFirstEnumeration();
while (e.hasMoreElements()) {
DefaultMutableTreeNode node
= (DefaultMutableTreeNode) e.nextElement();
if (node.isLeaf()) {
continue;
}
int row = tree.getRowForPath(new TreePath(node.getPath()));
tree.expandRow(row);
}
}
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.setLocation(200, 200);
f.setVisible(true);
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType
";class=\""
javax.swing.tree.DefaultMutableTreeNode[].class.getName()
"\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFound: " e.getMessage());
}
}
public boolean canImport(TransferHandler.TransferSupport support) {
if (!support.isDrop()) {
return false;
}
support.setShowDropLocation(true);
if (!support.isDataFlavorSupported(nodesFlavor)) {
System.out.println("Unsupported flavor");
return false;
}
// Do not allow a drop on the drag source selections.
JTree.DropLocation dl
= (JTree.DropLocation) support.getDropLocation();
JTree tree = (JTree) support.getComponent();
int dropRow = tree.getRowForPath(dl.getPath());
int[] selRows = tree.getSelectionRows();
for (int i = 0; i < selRows.length; i ) {
if (selRows[i] == dropRow) {
return false;
}
}
// This seems to stop the node from been copied to a level above itself?!
// TreePath dest = dl.getPath();
// DefaultMutableTreeNode target = (DefaultMutableTreeNode) dest.getLastPathComponent();
// TreePath path = tree.getPathForRow(selRows[0]);
// DefaultMutableTreeNode firstNode = (DefaultMutableTreeNode) path.getLastPathComponent();
// if (firstNode.getChildCount() > 0 && target.getLevel() < firstNode.getLevel()) {
// return false;
// }
return true;
}
protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
// Make up a node array of copies for transfer and
// another for/of the nodes that will be removed in
// exportDone after a successful drop.
List<DefaultMutableTreeNode> copies = new ArrayList<DefaultMutableTreeNode>();
for (int i = 0; i < paths.length; i ) {
DefaultMutableTreeNode next = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
System.out.println("Selected = " next.getUserObject());
copies.add(next);
}
DefaultMutableTreeNode[] nodes = copies.toArray(new DefaultMutableTreeNode[copies.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/**
* Defensive copy used in createTransferable.
*/
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
protected void exportDone(JComponent source, Transferable data, int action) {
// Already dealt with this
}
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public boolean importData(TransferHandler.TransferSupport support) {
System.out.println("Import here");
if (!canImport(support)) {
return false;
}
// Extract transfer data.
DefaultMutableTreeNode[] nodes = null;
try {
Transferable t = support.getTransferable();
nodes = (DefaultMutableTreeNode[]) t.getTransferData(nodesFlavor);
} catch (UnsupportedFlavorException ufe) {
System.out.println("UnsupportedFlavor: " ufe.getMessage());
} catch (java.io.IOException ioe) {
System.out.println("I/O error: " ioe.getMessage());
}
// Get drop location info.
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
int childIndex = dl.getChildIndex();
TreePath dest = dl.getPath();
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) dest.getLastPathComponent();
JTree tree = (JTree) support.getComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
// Configure for drop mode.
int index = childIndex; // DropMode.INSERT
if (childIndex == -1) { // DropMode.ON
index = parent.getChildCount();
}
// One consideration to consider is what to do if it's a different
// source model ... and it's only a "copy" operation
// Might want to look into that
for (DefaultMutableTreeNode node : nodes) {
model.removeNodeFromParent(node);
}
// Add data to model.
for (DefaultMutableTreeNode node : nodes) {
model.insertNodeInto(node, parent, index );
}
return true;
}
public String toString() {
return getClass().getName();
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException {
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return nodes;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return nodesFlavor.equals(flavor);
}
}
}
}
至于“我在網上找到的代碼”,這還不錯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/323038.html
上一篇:重置游戲生命指南
