JTextArea - поддерживать функциональность буфера обмена после настройки TransferHandler
Я следую приведенному здесь примеру, чтобы создать JTextArea, в который я могу добавить объект и выполнить какое-либо действие. Это отлично работает. Моя проблема заключается в том, что после установки TransferHandler с textArea.setTransferHandler(myTransferHandler) операции с буфером обмена, которые работают по умолчанию (вырезание, копирование и вставка текста), больше не работают.
Есть ли способ установить пользовательский TransferHandler в моей JTextArea, чтобы разрешить перетаскивание объектов, но не мешать работе буфера обмена по умолчанию в JTextArea? Если нет, то как проще всего изменить TransferHandler, чтобы обычные операции с буфером обмена продолжали работать в обычном режиме?
Обновление: вот пример, который иллюстрирует проблему. Я могу перетаскивать из дерева в текстовую область, но функциональность буфера обмена в текстовой области нарушена.
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.text.JTextComponent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
public class DnDTest
{
public DnDTest()
{
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeObject("root"));
root.add(new DefaultMutableTreeNode(new NodeObject("child1")));
root.add(new DefaultMutableTreeNode(new NodeObject("child2")));
JTree tree = new JTree(new DefaultTreeModel(root));
tree.setDragEnabled(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JTextArea textArea = new JTextArea();
textArea.setDragEnabled(true);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
NodeObjectTransferHandler transferHandler = new NodeObjectTransferHandler();
tree.setTransferHandler(transferHandler);
textArea.setTransferHandler(transferHandler);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(1,0));
f.add(new JScrollPane(tree));
f.add(new JScrollPane(textArea));
f.setSize(500,400);
f.setLocation(200,200);
f.setVisible(true);
}
public static void main(String[] args)
{
new DnDTest();
}
}
class NodeObject {
public String str;
public NodeObject(String str) { this.str = str; }
@Override
public String toString() { return str; }
}
class NodeObjectTransferHandler extends TransferHandler {
private static final long serialVersionUID = 1L;
private static final DataFlavor nodeObjectFlavor = new DataFlavor(NodeObject.class, "NodeObject");
@Override
public boolean importData(JComponent c, Transferable t)
{
if (!canImport(c, t.getTransferDataFlavors())) {
return false;
}
if (!(c instanceof JTextComponent)) {
return false;
}
try {
NodeObject nodeObject = (NodeObject) t.getTransferData(nodeObjectFlavor);
((JTextComponent) c).setText(nodeObject.str);
return true;
} catch (UnsupportedFlavorException e) {
} catch (IOException e) {
}
return false;
}
@Override
public Transferable createTransferable(JComponent c)
{
if (!(c instanceof JTree)) {
return null;
}
JTree tree = (JTree) c;
DefaultMutableTreeNode lastPathComponent = (DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent();
return new NodeObjectTransferable((NodeObject) lastPathComponent.getUserObject());
}
@Override
public int getSourceActions(JComponent c)
{
return COPY;
}
@Override
public boolean canImport(JComponent c, DataFlavor[] flavors)
{
for (DataFlavor flavor : flavors) {
if (flavor.match(nodeObjectFlavor)) {
return true;
}
}
return false;
}
}
class NodeObjectTransferable implements Transferable {
private static final DataFlavor nodeObjectFlavor = new DataFlavor(NodeObject.class, "NodeObject");
private NodeObject nodeObject;
public NodeObjectTransferable(NodeObject nodeObject) {
this.nodeObject = nodeObject;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (!isDataFlavorSupported(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return nodeObject;
}
@Override
public DataFlavor[] getTransferDataFlavors()
{
return new DataFlavor[] { nodeObjectFlavor };
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return flavor.match(nodeObjectFlavor);
}
};