java - 使用自己的对象从 JTree 拖放到 JList

标签 java swing drag-and-drop jlist jtree

我有一个带有 DefaultMutableTreeNodesJTree。在某些级别上,这些节点是用我自己的可序列化对象初始化的。总共有两种不同类型的对象(称为“步骤”和“顺序”)。我希望能够仅删除使用这两个对象之一初始化的节点。任何其他只是字符串的节点都不应该被删除。一个“订单”可以包含多个“步骤”。我希望能够将它们拖到 JPanel 上,然后将它们插入到 JList 中。如果删除了“订单”,则应插入所有“步骤”,如果仅删除“步骤”,则仅删除该“步骤”应该插入特定的“Step”。

下面是 SSCCE!

J树:

tree = new JTree();
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.setDragEnabled(true);
tree.setModel(treeModel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

JPanel:

public class TablePanel extends JPanel
{
    private static final long serialVersionUID = 3216206960422611905L;

    public TablePanel()
    {
        super();

        setLayout(new MigLayout("", "[grow]", "[][grow]"));

        JProgressBar progressBar = new JProgressBar();
        progressBar.setMaximum(28800); // 8 hours in seconds
        progressBar.setStringPainted(true);
        add(progressBar, "cell 0 0,growx");

        DefaultListModel<Step> listModel = new DefaultListModel<Step>();

        JList<Step> list = new JList<Step>();
        list.setModel(listModel);

        setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
        {
            private int    index    = 0;
            private int    amount    = 0;

            @Override
            public void drop(DropTargetDropEvent dtde)
            {
                amount = 0;
                index = 0;
            }

            @Override
            public void dragExit(DropTargetEvent dte)
            {
                if (listModel.size() > 0)
                {
                    if (amount == 1)
                    {
                        listModel.remove(index);
                    }
                    else
                    {
                        for (int i = 0; i < amount; i++)
                        {
                            listModel.remove(index + i);
                        }
                    }

                    amount = 0;
                }
            }

            @Override
            public void dragEnter(DropTargetDragEvent dtde)
            {
                try
                {
                    Transferable tr = dtde.getTransferable();
                    if (dtde.isDataFlavorSupported(Order.auftragFlavor))
                    {
                        Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?

                        dtde.acceptDrag(DnDConstants.ACTION_COPY);

                        amount = a.getSteps().size();

                    }
                    else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
                    {
                        Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);

                        dtde.acceptDrag(DnDConstants.ACTION_COPY);

                        amount = 1;
                    }
                    else
                    {
                        dtde.rejectDrag();
                    }
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    dtde.rejectDrag();
                }
            }

            @Override
            public void dragOver(DropTargetDragEvent dtde)
            {
                try
                {
                    Transferable tr = dtde.getTransferable();
                    if (dtde.isDataFlavorSupported(Order.auftragFlavor))
                    {
                        Order a = (Order) tr.getTransferData(Order.auftragFlavor); // Wrong, how do I get this?

                        dtde.acceptDrag(DnDConstants.ACTION_COPY);

                        amount = a.getSteps().size();
                    }
                    else if (dtde.isDataFlavorSupported(Step.arbeitsgangFlavor))
                    {
                        Step ag = (Step) tr.getTransferData(Step.arbeitsgangFlavor);

                        dtde.acceptDrag(DnDConstants.ACTION_COPY);

                        amount = 1;
                    }
                    else dtde.rejectDrag();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    dtde.rejectDrag();
                }
            }
        }, true, null));

        add(list, "cell 0 1,grow");
    }
}

当您在 JList 上拖动时,数据应该被插入到列表中,以向用户提供反馈以及将其放入列表中的可能性。如果没有删除,则应再次删除。

如何将我的对象拖放到 JPanel 上,而不是只是字符串的节点?

编辑: 使用 (String) tr.getTransferData(DataFlavor.stringFlavor) 我能够获取节点的标签,但这并没有多大帮助,因为我不知道它是否是 顺序步骤或只是一个字符串节点。

编辑2 SSCCE:

public class Test extends JFrame
{
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    Test window = new Test();
                    window.setVisible(true);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }

    public Test()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
        DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
        DefaultMutableTreeNode order1 = new DefaultMutableTreeNode(new ParentObject());
        order1.add(new DefaultMutableTreeNode(new ChildObject()));
        order1.add(new DefaultMutableTreeNode(new ChildObject()));

        string1.add(order1);

        root.add(string1);

        DefaultTreeModel model = new DefaultTreeModel(root);

        JTree tree = new JTree(model);
        tree.setShowsRootHandles(true);
        tree.setRootVisible(false);
        tree.setDragEnabled(true);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        contentPane.add(tree, BorderLayout.WEST);

        CustPanel panel = new CustPanel();
        contentPane.add(panel, BorderLayout.CENTER);
    }
}

class CustPanel extends JPanel
{
    private static final long serialVersionUID = 1L;

    public CustPanel()
    {
        super();
        setLayout(new MigLayout("", "[grow]", "[][grow]"));

        JProgressBar progressBar = new JProgressBar();
        add(progressBar, "cell 0 0,growx");

        DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();

        JList<ChildObject> list = new JList<ChildObject>();
        list.setModel(listModel);

        setDropTarget(new DropTarget(this, TransferHandler.COPY, new DropTargetAdapter()
        {
            @Override
            public void drop(DropTargetDropEvent dtde)
            {
                Transferable tr = dtde.getTransferable();
                if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
                {
                    try
                    {
                        System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
                    }
                    catch (UnsupportedFlavorException | IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void dragExit(DropTargetEvent dte)
            {

            }

            @Override
            public void dragEnter(DropTargetDragEvent dtde)
            {
                Transferable tr = dtde.getTransferable();
                if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
                {
                    try
                    {
                        System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
                    }
                    catch (UnsupportedFlavorException | IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void dragOver(DropTargetDragEvent dtde)
            {
                Transferable tr = dtde.getTransferable();
                if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor))
                {
                    try
                    {
                        System.out.println((String) tr.getTransferData(DataFlavor.stringFlavor)); // I want the actual object
                    }
                    catch (UnsupportedFlavorException | IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }, true, null));

        add(list, "cell 0 1,grow");
    }
}

class ParentObject implements Serializable
{
    private static final long serialVersionUID = 1279985471254050120L;

    public ArrayList<ChildObject> getChildren()
    {
        return new ArrayList<ChildObject>();
    }

    @Override
    public String toString()
    {
        return "ParentObject";
    }
}

class ChildObject implements Serializable
{
    private static final long serialVersionUID = -5833860202973614790L;

    @Override
    public String toString()
    {
        return "ChildObject";
    }
}

最佳答案

but not nodes which are just Strings?

您也许可以使用 TransferHandler#createTransferable(...) 方法来获取 DefaultMutableTreeNode

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.*;
import javax.activation.*;
import javax.swing.*;
import javax.swing.tree.*;

public class Test2 {
  public JComponent makeUI() {
    DefaultMutableTreeNode root    = new DefaultMutableTreeNode("root");
    DefaultMutableTreeNode string1 = new DefaultMutableTreeNode("String 1");
    DefaultMutableTreeNode order1  = new DefaultMutableTreeNode(new ParentObject());
    order1.add(new DefaultMutableTreeNode(new ChildObject()));
    order1.add(new DefaultMutableTreeNode(new ChildObject()));
    string1.add(order1);
    root.add(string1);

    DefaultTreeModel model = new DefaultTreeModel(root);
    JTree tree = new JTree(model);
    tree.setShowsRootHandles(true);
    tree.setRootVisible(false);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setTransferHandler(new TreeTransferHandler());
    tree.setDragEnabled(true);

    DefaultListModel<ChildObject> listModel = new DefaultListModel<ChildObject>();
    JList<ChildObject> list = new JList<ChildObject>();
    list.setModel(listModel);
    list.setDropTarget(new DropTarget(list, TransferHandler.COPY, new DropTargetAdapter() {
      private void print(Transferable tr) {
        try {
          Object node = tr.getTransferData(TreeTransferHandler.FLAVOR);
          System.out.println(node); // I want the actual object
        } catch (UnsupportedFlavorException | IOException ex) {
          ex.printStackTrace();
        }
      }
      @Override
      public void drop(DropTargetDropEvent dtde) {
        if (dtde.isDataFlavorSupported(TreeTransferHandler.FLAVOR)) {
          print(dtde.getTransferable());
        }
      }
      @Override public void dragExit(DropTargetEvent dte) {}
      @Override public void dragEnter(DropTargetDragEvent dtde) {}
      @Override public void dragOver(DropTargetDragEvent dtde) {}
    }, true, null));

    JPanel contentPane = new JPanel(new GridLayout(1, 2));
    contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    contentPane.add(new JScrollPane(tree), BorderLayout.WEST);
    contentPane.add(new JScrollPane(list), BorderLayout.CENTER);

    return contentPane;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        try {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.getContentPane().add(new Test2().makeUI());
          f.setBounds(100, 100, 450, 300);
          f.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }
}

class ParentObject implements Serializable {
  public ArrayList<ChildObject> getChildren() {
    return new ArrayList<ChildObject>();
  }
  @Override
  public String toString() {
    return "ParentObject";
  }
}

class ChildObject implements Serializable {
  @Override
  public String toString() {
    return "ChildObject";
  }
}

class TreeTransferHandler extends TransferHandler {
  public static final DataFlavor FLAVOR = new ActivationDataFlavor(
    DefaultMutableTreeNode[].class,
    DataFlavor.javaJVMLocalObjectMimeType,
    "Array of DefaultMutableTreeNode");
  @Override protected Transferable createTransferable(JComponent c) {
    JTree source = (JTree) c;
    TreePath[] paths = source.getSelectionPaths();
    DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[paths.length];
    for (int i = 0; i < paths.length; i++) {
      nodes[i] = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
    }
    return new DataHandler(nodes, FLAVOR.getMimeType());
  }
  @Override public int getSourceActions(JComponent c) {
    return TransferHandler.COPY;
  }
}

关于java - 使用自己的对象从 JTree 拖放到 JList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39513076/

相关文章:

java - 如何创建可滚动的 JPopupMenu

java - 无法使用 Tomcat 5.5 和 Hibernate 连接到数据库

java - 将 select inside insert 查询与 preparedStatement 一起使用

java - 如何强制 JTextPane 不转到下一行?

Java 显示带有任务栏但没有标题栏的全屏 swing 应用程序

ios - 将对象移动到特定区域

java - 在android上拖放一个按钮..帮助

javascript - 子元素允许拖放

java - Groovy JasperReport 缺少方法异常,可能的解决方案被列为我调用的方法

java - java 中的 nextFloat 问题