从 JTree Transferable TransferHandler 复制粘贴
Copy Paste from JTree Transferable TransferHandler
我正在研究如何实施 JTree
的 Copy
和 Paste
。
因为,我想从 DefaultMutableTreeNode
像 toString()
一样复制粘贴到另一个应用程序,如 Sublime Text。
我查看代码是为了查看 how copy & paste is implemented and how is used drag and drop in JTree。
我的第一个想法是,必须测试 JTree
的 DefaultMutableTreeNode
之间的复制和粘贴,稍后如何从剪贴板粘贴到另一个应用程序,但我的代码不工作,不知道为什么失败了,我需要解决。
注意:抱歉我的代码有点长,因为如果我只放一段代码将无法使用。对我来说,这里的所有代码都需要进行测试。
这是我的代码:
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
public class JTreeTransferHandler extends JFrame {
public JTreeTransferHandler() {
initiate();
}
private void initiate() {
setTitle("Copy from JTree");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setLocation(200,200);
setVisible(true);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
fruitNode.add(new DefaultMutableTreeNode("Mango"));
fruitNode.add(new DefaultMutableTreeNode("Apple"));
root.add(vegetableNode);
root.add(fruitNode);
JTree tree = new JTree(root);
TreeTransferHandler treeTransferHandler = new TreeTransferHandler();
tree.setTransferHandler(treeTransferHandler);
Clipboard clipboard = this.getToolkit().getSystemClipboard();
JButton copy = new JButton("Copy");
copy.addActionListener((ActionEvent e) -> {
TransferHandler handler = tree.getTransferHandler();
handler.exportToClipboard(tree, clipboard, TransferHandler.COPY);
});
JButton paste = new JButton("Paste");
paste.addActionListener((ActionEvent e) -> {
Transferable clipData = clipboard.getContents(clipboard);
if (clipData != null) {
if (clipData.isDataFlavorSupported(treeTransferHandler.nodesFlavor)) {
TransferHandler handler = tree.getTransferHandler();
handler.importData(tree, clipData);
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(copy);
buttonsPanel.add(paste);
add(new JScrollPane(tree), BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTreeTransferHandler jTreeTransferHandler = new JTreeTransferHandler();
});
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +
DefaultMutableTreeNode[].class.getName() + "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
//TransferHandler
@Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
//TransferHandler
@Override public boolean canImport(JComponent comp, DataFlavor flavor[]) {
for (int i = 0, n = flavor.length; i < n; i++) {
for (int j = 0, m = flavors.length; j < m; j++) {
if (flavor[i].equals(flavors[j])) {
return true;
}
}
}
return false;
}
//TransferHandler
@Override protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
List<DefaultMutableTreeNode> copies = new ArrayList<>();
List<DefaultMutableTreeNode> toRemove = new ArrayList<>();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for (int i = 1; i < paths.length; i++) {
DefaultMutableTreeNode next =
(DefaultMutableTreeNode) paths[i].getLastPathComponent();
// Do not allow higher level nodes to be added to list.
if (next.getLevel() < node.getLevel()) {
break;
} else if (next.getLevel() > node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
//TransferHandler
@Override public boolean importData(TransferHandler.TransferSupport support) {
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();
}
// Add data to model.
for (int i = 0; i < nodes.length; i++) {
model.insertNodeInto(nodes[i], parent, index++);
}
return true;
}
//TransferHandler
public boolean importData(JComponent comp, Transferable t) {
// Extract transfer data.
DefaultMutableTreeNode[] nodes;
try {
nodes = (DefaultMutableTreeNode[]) t.getTransferData(nodesFlavor);
if (comp instanceof JTree) {
JTree tree = (JTree)comp;
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
JTree.DropLocation dl = tree.getDropLocation();
int childIndex = dl.getChildIndex();
TreePath dest = dl.getPath();
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode)dest.getLastPathComponent();
// Configure for drop mode.
int index = childIndex; // DropMode.INSERT
if (childIndex == -1) { // DropMode.ON
index = parent.getChildCount();
}
// Add data to model.
for (DefaultMutableTreeNode node : nodes) {
model.insertNodeInto(node, parent, index++);
}
return true;
}
} catch (UnsupportedFlavorException ufe) {
System.out.println("UnsupportedFlavor: " + ufe.getMessage());
} catch (java.io.IOException ioe) {
System.out.println("I/O error: " + ioe.getMessage());
}
return false;
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
//Transferable
@Override public Object getTransferData(DataFlavor flavor) {
if(!isDataFlavorSupported(flavor)) {
return false;
}
return nodes;
}
//Transferable
@Override public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
//Transferable
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(nodesFlavor);
}
}
}
TransferHandler.TransferSupport#isDrop() 方法 returns false
在 via Clipboard
的情况下,所以在这里切换它似乎工作正常。
// Get drop location info.
int childIndex;
TreePath dest;
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
childIndex = dl.getChildIndex();
dest = dl.getPath();
} else {
childIndex = -1;
JTree tree = (JTree) support.getComponent();
dest = tree.getSelectionPath();
}
JTreeTransferHandler2.java
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.tree.*;
public class JTreeTransferHandler2 extends JFrame {
public JTreeTransferHandler2() {
initiate();
}
private void initiate() {
setTitle("Copy from JTree");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setLocation(200,200);
setVisible(true);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
fruitNode.add(new DefaultMutableTreeNode("Mango"));
fruitNode.add(new DefaultMutableTreeNode("Apple"));
root.add(vegetableNode);
root.add(fruitNode);
JTree tree = new JTree(root);
TreeTransferHandler treeTransferHandler = new TreeTransferHandler();
tree.setTransferHandler(treeTransferHandler);
Clipboard clipboard = this.getToolkit().getSystemClipboard();
JButton copy = new JButton("Copy");
copy.addActionListener((ActionEvent e) -> {
TransferHandler handler = tree.getTransferHandler();
handler.exportToClipboard(tree, clipboard, TransferHandler.COPY);
});
JButton paste = new JButton("Paste");
paste.addActionListener((ActionEvent e) -> {
Transferable clipData = clipboard.getContents(null);
if (clipData != null) {
if (clipData.isDataFlavorSupported(treeTransferHandler.nodesFlavor)) {
TransferHandler handler = tree.getTransferHandler();
handler.importData(tree, clipData);
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(copy);
buttonsPanel.add(paste);
add(new JScrollPane(tree), BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTreeTransferHandler2 jTreeTransferHandler = new JTreeTransferHandler2();
});
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +
DefaultMutableTreeNode[].class.getName() + "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
//TransferHandler
@Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
//TransferHandler
@Override public boolean canImport(JComponent comp, DataFlavor flavor[]) {
for (int i = 0, n = flavor.length; i < n; i++) {
for (int j = 0, m = flavors.length; j < m; j++) {
if (flavor[i].equals(flavors[j])) {
return true;
}
}
}
return false;
}
//TransferHandler
@Override protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
List<DefaultMutableTreeNode> copies = new ArrayList<>();
List<DefaultMutableTreeNode> toRemove = new ArrayList<>();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for (int i = 1; i < paths.length; i++) {
DefaultMutableTreeNode next =
(DefaultMutableTreeNode) paths[i].getLastPathComponent();
// Do not allow higher level nodes to be added to list.
if (next.getLevel() < node.getLevel()) {
break;
} else if (next.getLevel() > node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
//TransferHandler
@Override public boolean importData(TransferHandler.TransferSupport support) {
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.
int childIndex;
TreePath dest;
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
childIndex = dl.getChildIndex();
dest = dl.getPath();
} else {
childIndex = -1;
JTree tree = (JTree) support.getComponent();
dest = tree.getSelectionPath();
}
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();
}
// Add data to model.
for (int i = 0; i < nodes.length; i++) {
// ArrayIndexOutOfBoundsException
model.insertNodeInto(nodes[i], parent, index++);
}
return true;
}
//TransferHandler
@Override public boolean importData(JComponent comp, Transferable t) {
return importData(new TransferHandler.TransferSupport(comp, t));
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
//Transferable
@Override public Object getTransferData(DataFlavor flavor) {
if(!isDataFlavorSupported(flavor)) {
return false;
}
return nodes;
}
//Transferable
@Override public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
//Transferable
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(nodesFlavor);
}
}
}
我正在研究如何实施 JTree
的 Copy
和 Paste
。
因为,我想从 DefaultMutableTreeNode
像 toString()
一样复制粘贴到另一个应用程序,如 Sublime Text。
我查看代码是为了查看 how copy & paste is implemented and how is used drag and drop in JTree。
我的第一个想法是,必须测试 JTree
的 DefaultMutableTreeNode
之间的复制和粘贴,稍后如何从剪贴板粘贴到另一个应用程序,但我的代码不工作,不知道为什么失败了,我需要解决。
注意:抱歉我的代码有点长,因为如果我只放一段代码将无法使用。对我来说,这里的所有代码都需要进行测试。
这是我的代码:
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
public class JTreeTransferHandler extends JFrame {
public JTreeTransferHandler() {
initiate();
}
private void initiate() {
setTitle("Copy from JTree");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setLocation(200,200);
setVisible(true);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
fruitNode.add(new DefaultMutableTreeNode("Mango"));
fruitNode.add(new DefaultMutableTreeNode("Apple"));
root.add(vegetableNode);
root.add(fruitNode);
JTree tree = new JTree(root);
TreeTransferHandler treeTransferHandler = new TreeTransferHandler();
tree.setTransferHandler(treeTransferHandler);
Clipboard clipboard = this.getToolkit().getSystemClipboard();
JButton copy = new JButton("Copy");
copy.addActionListener((ActionEvent e) -> {
TransferHandler handler = tree.getTransferHandler();
handler.exportToClipboard(tree, clipboard, TransferHandler.COPY);
});
JButton paste = new JButton("Paste");
paste.addActionListener((ActionEvent e) -> {
Transferable clipData = clipboard.getContents(clipboard);
if (clipData != null) {
if (clipData.isDataFlavorSupported(treeTransferHandler.nodesFlavor)) {
TransferHandler handler = tree.getTransferHandler();
handler.importData(tree, clipData);
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(copy);
buttonsPanel.add(paste);
add(new JScrollPane(tree), BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTreeTransferHandler jTreeTransferHandler = new JTreeTransferHandler();
});
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +
DefaultMutableTreeNode[].class.getName() + "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
//TransferHandler
@Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
//TransferHandler
@Override public boolean canImport(JComponent comp, DataFlavor flavor[]) {
for (int i = 0, n = flavor.length; i < n; i++) {
for (int j = 0, m = flavors.length; j < m; j++) {
if (flavor[i].equals(flavors[j])) {
return true;
}
}
}
return false;
}
//TransferHandler
@Override protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
List<DefaultMutableTreeNode> copies = new ArrayList<>();
List<DefaultMutableTreeNode> toRemove = new ArrayList<>();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for (int i = 1; i < paths.length; i++) {
DefaultMutableTreeNode next =
(DefaultMutableTreeNode) paths[i].getLastPathComponent();
// Do not allow higher level nodes to be added to list.
if (next.getLevel() < node.getLevel()) {
break;
} else if (next.getLevel() > node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
//TransferHandler
@Override public boolean importData(TransferHandler.TransferSupport support) {
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();
}
// Add data to model.
for (int i = 0; i < nodes.length; i++) {
model.insertNodeInto(nodes[i], parent, index++);
}
return true;
}
//TransferHandler
public boolean importData(JComponent comp, Transferable t) {
// Extract transfer data.
DefaultMutableTreeNode[] nodes;
try {
nodes = (DefaultMutableTreeNode[]) t.getTransferData(nodesFlavor);
if (comp instanceof JTree) {
JTree tree = (JTree)comp;
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
JTree.DropLocation dl = tree.getDropLocation();
int childIndex = dl.getChildIndex();
TreePath dest = dl.getPath();
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode)dest.getLastPathComponent();
// Configure for drop mode.
int index = childIndex; // DropMode.INSERT
if (childIndex == -1) { // DropMode.ON
index = parent.getChildCount();
}
// Add data to model.
for (DefaultMutableTreeNode node : nodes) {
model.insertNodeInto(node, parent, index++);
}
return true;
}
} catch (UnsupportedFlavorException ufe) {
System.out.println("UnsupportedFlavor: " + ufe.getMessage());
} catch (java.io.IOException ioe) {
System.out.println("I/O error: " + ioe.getMessage());
}
return false;
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
//Transferable
@Override public Object getTransferData(DataFlavor flavor) {
if(!isDataFlavorSupported(flavor)) {
return false;
}
return nodes;
}
//Transferable
@Override public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
//Transferable
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(nodesFlavor);
}
}
}
TransferHandler.TransferSupport#isDrop() 方法 returns false
在 via Clipboard
的情况下,所以在这里切换它似乎工作正常。
// Get drop location info.
int childIndex;
TreePath dest;
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
childIndex = dl.getChildIndex();
dest = dl.getPath();
} else {
childIndex = -1;
JTree tree = (JTree) support.getComponent();
dest = tree.getSelectionPath();
}
JTreeTransferHandler2.java
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.tree.*;
public class JTreeTransferHandler2 extends JFrame {
public JTreeTransferHandler2() {
initiate();
}
private void initiate() {
setTitle("Copy from JTree");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,400);
setLocation(200,200);
setVisible(true);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode vegetableNode = new DefaultMutableTreeNode("Vegetables");
vegetableNode.add(new DefaultMutableTreeNode("Capsicum"));
vegetableNode.add(new DefaultMutableTreeNode("Carrot"));
DefaultMutableTreeNode fruitNode = new DefaultMutableTreeNode("Fruits");
fruitNode.add(new DefaultMutableTreeNode("Mango"));
fruitNode.add(new DefaultMutableTreeNode("Apple"));
root.add(vegetableNode);
root.add(fruitNode);
JTree tree = new JTree(root);
TreeTransferHandler treeTransferHandler = new TreeTransferHandler();
tree.setTransferHandler(treeTransferHandler);
Clipboard clipboard = this.getToolkit().getSystemClipboard();
JButton copy = new JButton("Copy");
copy.addActionListener((ActionEvent e) -> {
TransferHandler handler = tree.getTransferHandler();
handler.exportToClipboard(tree, clipboard, TransferHandler.COPY);
});
JButton paste = new JButton("Paste");
paste.addActionListener((ActionEvent e) -> {
Transferable clipData = clipboard.getContents(null);
if (clipData != null) {
if (clipData.isDataFlavorSupported(treeTransferHandler.nodesFlavor)) {
TransferHandler handler = tree.getTransferHandler();
handler.importData(tree, clipData);
}
}
});
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(copy);
buttonsPanel.add(paste);
add(new JScrollPane(tree), BorderLayout.CENTER);
add(buttonsPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTreeTransferHandler2 jTreeTransferHandler = new JTreeTransferHandler2();
});
}
}
class TreeTransferHandler extends TransferHandler {
DataFlavor nodesFlavor;
DataFlavor[] flavors = new DataFlavor[1];
DefaultMutableTreeNode[] nodesToRemove;
public TreeTransferHandler() {
try {
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" +
DefaultMutableTreeNode[].class.getName() + "\"";
nodesFlavor = new DataFlavor(mimeType);
flavors[0] = nodesFlavor;
} catch(ClassNotFoundException e) {
System.out.println("ClassNotFound: " + e.getMessage());
}
}
//TransferHandler
@Override public int getSourceActions(JComponent c) {
return TransferHandler.COPY;
}
//TransferHandler
@Override public boolean canImport(JComponent comp, DataFlavor flavor[]) {
for (int i = 0, n = flavor.length; i < n; i++) {
for (int j = 0, m = flavors.length; j < m; j++) {
if (flavor[i].equals(flavors[j])) {
return true;
}
}
}
return false;
}
//TransferHandler
@Override protected Transferable createTransferable(JComponent c) {
JTree tree = (JTree) c;
TreePath[] paths = tree.getSelectionPaths();
if (paths != null) {
List<DefaultMutableTreeNode> copies = new ArrayList<>();
List<DefaultMutableTreeNode> toRemove = new ArrayList<>();
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) paths[0].getLastPathComponent();
DefaultMutableTreeNode copy = copy(node);
copies.add(copy);
toRemove.add(node);
for (int i = 1; i < paths.length; i++) {
DefaultMutableTreeNode next =
(DefaultMutableTreeNode) paths[i].getLastPathComponent();
// Do not allow higher level nodes to be added to list.
if (next.getLevel() < node.getLevel()) {
break;
} else if (next.getLevel() > node.getLevel()) { // child node
copy.add(copy(next));
// node already contains child
} else { // sibling
copies.add(copy(next));
toRemove.add(next);
}
}
DefaultMutableTreeNode[] nodes =
copies.toArray(new DefaultMutableTreeNode[copies.size()]);
nodesToRemove =
toRemove.toArray(new DefaultMutableTreeNode[toRemove.size()]);
return new NodesTransferable(nodes);
}
return null;
}
/** Defensive copy used in createTransferable. */
private DefaultMutableTreeNode copy(TreeNode node) {
return new DefaultMutableTreeNode(node);
}
//TransferHandler
@Override public boolean importData(TransferHandler.TransferSupport support) {
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.
int childIndex;
TreePath dest;
if (support.isDrop()) {
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
childIndex = dl.getChildIndex();
dest = dl.getPath();
} else {
childIndex = -1;
JTree tree = (JTree) support.getComponent();
dest = tree.getSelectionPath();
}
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();
}
// Add data to model.
for (int i = 0; i < nodes.length; i++) {
// ArrayIndexOutOfBoundsException
model.insertNodeInto(nodes[i], parent, index++);
}
return true;
}
//TransferHandler
@Override public boolean importData(JComponent comp, Transferable t) {
return importData(new TransferHandler.TransferSupport(comp, t));
}
public class NodesTransferable implements Transferable {
DefaultMutableTreeNode[] nodes;
public NodesTransferable(DefaultMutableTreeNode[] nodes) {
this.nodes = nodes;
}
//Transferable
@Override public Object getTransferData(DataFlavor flavor) {
if(!isDataFlavorSupported(flavor)) {
return false;
}
return nodes;
}
//Transferable
@Override public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
//Transferable
@Override public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(nodesFlavor);
}
}
}