Как реализовать интеллектуальное перетаскивание из одного JTree в другое? - PullRequest
5 голосов
/ 30 марта 2012

У меня есть два дерева JT с некоторыми фиктивными данными, и я хочу, чтобы я мог взять каждое «задание» (15663-1, 15663-2 и т. Д.) И создать узел для каждого с узел для каждой части под ним и компоненты, прикрепленные к каждой части под ним. На двух деревьях вот так:

+------------------------------+------------------------------+
| PARTS TO BE SHIPPED          | SHIPPING BOX                 |
+------------------------------+------------------------------+
|[JOB]                         |[JOB]                         |
|+------[part]                 |+------[part]                | 
|        +------[component]    |        +------[component]    |
|        +------[component]    |        +------[component]    |
|+------[part]                 |+------[part]                 |
|        +------[component]    |        +------[component]    |
|[JOB]                         |[JOB]                         |
|+------[part]                 |+------[part]                 |
|        +------[component]    |        +------[component]    |
|        +------[component]    |        +------[component]    |
|+------[part]                 |+------[part]                 |
|        +------[component]    |        +------[component]    |
+------------------------------+------------------------------+

Итак, предположим, что у меня есть два винта в крышке в задании A в дереве «детали для отправки», и у меня нет ничего в задании A в транспортной коробке, когда я перетаскиваю винты в транспортную коробку, это должен сделать запись для задания A, сделать запись для части A и сделать запись для компонента, затем я хочу, чтобы он запрашивал количество для этого компонента и вычитал это количество из частей, которые должны быть отправлены jtree.

Итак, если у меня есть задание 1553-4, у которого есть крышка с четырьмя винтами, и я перетаскиваю винты в транспортировочную коробку, тогда в поле доставки должно быть указано «х винтов», а затем запросить пользователь должен ввести количество винтов, которые он только что упаковал, если они упаковывают два винта, тогда jtree должен измениться, чтобы отразить 2 винта, оставшиеся для этой работы.

Я прочитал кучу разных уроков по перетаскиванию, и у меня есть несколько примеров, но я просто не могу это понять. Любой совет или помощь будут оценены.

Я знаю, что мне нужно реализовать TranferHandler, но я точно не знаю, как, кажется, слишком много «волшебства» интерфейса происходит, и я действительно не понимаю этого.

Это то, что у меня есть, я понимаю создание узлов и тому подобное, вот что у меня есть:

package com.protocase.examples;


import java.awt.Dimension;
import java.awt.HeadlessException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;

/**
 * @author DavidH
 */
public class JTreeExample {
    public static void main(String[] args) {
        addTreesAndDisplay();

    }

    private static void addTreesAndDisplay() throws HeadlessException {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();


        JTree tree = new JTree(getTreeModel());
        tree.setDragEnabled(true);
        tree.setPreferredSize(new Dimension(200,400));
        JScrollPane scroll = new JScrollPane();
        scroll.setViewportView(tree);
        panel.add(scroll);


        JTree secondTree = new JTree(getTreeModel());
        secondTree.setPreferredSize(new Dimension(200,400));
        secondTree.setDragEnabled(true);
        JScrollPane secondScroll = new JScrollPane();
        secondScroll.setViewportView(secondTree);
        panel.add(secondScroll);


        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private static DefaultTreeModel getTreeModel() {
        MutableTreeNode root =  new DefaultMutableTreeNode("15663-1");
        DefaultMutableTreeNode cover = new DefaultMutableTreeNode("Cover");
        DefaultMutableTreeNode base = new DefaultMutableTreeNode("Base");
        root.insert(cover, 0);
        root.insert(base, 0);
        cover.insert(new DefaultMutableTreeNode("2x PEMS"), 0);
        cover.insert(new DefaultMutableTreeNode("2x SCREWS"), 0);
        base.insert(new DefaultMutableTreeNode("4x SCREWS"), 0);
        base.insert(new DefaultMutableTreeNode("4x HANDLES"), 0);
        DefaultTreeModel model = new DefaultTreeModel(root);
        return model;
    }
}

Я просто ищу краткий пример перетаскивания в JTree и перетаскивания из JTree.

Ответы [ 2 ]

3 голосов
/ 31 марта 2012

Очень короткое, простое введение в Drag and Drop в Swing моими собственными словами, основанное на моем собственном опыте (в основном это было с помощью drag-and-drop в JDK1.5, поэтому новые функциональные возможности уже могут присутствовать).

В операции перетаскивания есть две части.Сначала происходит перетаскивание из исходного компонента.TransferHandler исходного компонента создает Transferable, который является контейнером для данных, которыми будут обмениваться в операции перетаскивания.В зависимости от данных могут быть разные представления данных (которые называются DataFlavor с).Например, если вы перетащите URL-адрес в текстовый редактор, он, скорее всего, добавит URL-адрес в текущий документ.Но если вы поместите его в веб-браузер, вы надеетесь, что он откроет этот URL.Поэтому, когда первое просто заинтересовано в простом тексте, второе может заинтересоваться более сложным объектом.

Вторая часть - это капля.Сначала решается, является ли текущее местоположение хорошей целью сбрасывания.Именно обработчик передачи целевого компонента должен решить, принимает ли он отбрасывание.Обычно это достигается проверкой того, может ли он обрабатывать данные, содержащиеся в Transferable, путем запроса Transferable данных для конкретного DataFlavor (примечание: Flavor должен быть известен как исходный и целевой компоненты).Когда он принимает отбрасывание и пользователь отпускает мышь, он может приступить к обработке данных в Transferable и, надеюсь, сделать что-нибудь полезное с ним.

Но, как всегда, Swing tutorials - очень хорошая отправная точка.После того, как вы их изучите, вы, вероятно, сможете задать более подробный вопрос (если он у вас еще есть, поскольку ваше требование довольно тривиально)

2 голосов
/ 04 апреля 2012

По теории, я думаю, что Робин ответил на ваш вопрос хорошо. Ниже приведена реализация, которую я сделал. Подводя итог, реализация включает в себя две верхние метки и две нижние полосы прокрутки, перетаскивая слева направо. Есть еще небольшая вещь, как до импорта, должно появиться диалоговое окно, спрашивающее пользователя, сколько нужно отбросить (а затем выполнить арифметическую операцию), но я думаю, что это может быть вашей домашней работой? ;-) Дайте мне знать, если вам нужна дополнительная помощь.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

public class JTreeExample extends JPanel
{
    private JTree tree;
    private DefaultTreeModel treeModel;


    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {

            @Override
            public void run()
            {
                createAndShowGUI();             
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("My Warehouse");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JTreeExample newContentPane = new JTreeExample();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);

        frame.pack();
        frame.setVisible(true);
    }

    public JTreeExample()
    {
        setLayout(new GridLayout(1, 3));
        JLabel lbl_parts = new JLabel("PARTS TO BE SHIPPED");       
        tree = new JTree(getTreeModel());
        tree.setDragEnabled(true);        
        tree.setPreferredSize(new Dimension(200,400));
        JScrollPane scroll = new JScrollPane();
        scroll.setViewportView(tree);

        JLabel lbl_ship = new JLabel("SHIPPING BOX");
        treeModel = getTreeModel();
        JTree secondTree = new JTree(treeModel);
        secondTree.setPreferredSize(new Dimension(200,400));        
        secondTree.setTransferHandler(new TransferHandler() {

            @Override
            public boolean importData(TransferSupport support)
            {
                if (!canImport(support))
                {
                    return false;
                }

                JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();

                TreePath path = dl.getPath();
                int childIndex = dl.getChildIndex();

                String data;
                try
                {
                    data = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
                }
                catch (UnsupportedFlavorException e)
                {
                    return false;                   
                }
                catch (IOException e)
                {
                    return false;                   
                }

                if (childIndex == -1)
                {
                    childIndex = tree.getModel().getChildCount(path.getLastPathComponent());
                }

                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data);
                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) path.getLastPathComponent();
                treeModel.insertNodeInto(newNode, parentNode, childIndex);

                tree.makeVisible(path.pathByAddingChild(newNode));
                tree.scrollRectToVisible(tree.getPathBounds(path.pathByAddingChild(newNode)));

                return true;
            }

            public boolean canImport(TransferSupport support)
            {
                if (!support.isDrop())
                {
                    return false;                   
                }

                support.setShowDropLocation(true);
                if (!support.isDataFlavorSupported(DataFlavor.stringFlavor))
                {
                    System.err.println("only string is supported");
                    return false;                   
                }

                JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();

                TreePath path = dl.getPath();

                if (path == null)
                {
                    return false;                   
                }
                return true;
            }                       
        });
        JScrollPane secondScroll = new JScrollPane();
        secondScroll.setViewportView(secondTree);

        JPanel topPanel = new JPanel(new BorderLayout());
        topPanel.add(lbl_parts, BorderLayout.NORTH);
        topPanel.add(scroll, BorderLayout.CENTER);

        JPanel btmPanel = new JPanel(new BorderLayout());
        btmPanel.add(lbl_ship, BorderLayout.NORTH);
        btmPanel.add(secondScroll, BorderLayout.CENTER);

        add(topPanel);
        add(btmPanel);        

    }

    private static DefaultTreeModel getTreeModel()
    {
        MutableTreeNode root =  new DefaultMutableTreeNode("15663-1");                        

        DefaultMutableTreeNode cover = new DefaultMutableTreeNode("Cover");
        cover.insert(new DefaultMutableTreeNode("2x PEMS"), 0);
        cover.insert(new DefaultMutableTreeNode("2x SCREWS"), 0);
        root.insert(cover, 0);

        DefaultMutableTreeNode base = new DefaultMutableTreeNode("Base");
        base.insert(new DefaultMutableTreeNode("4x SCREWS"), 0);
        base.insert(new DefaultMutableTreeNode("4x HANDLES"), 0);
        root.insert(base, 0);

        DefaultTreeModel model = new DefaultTreeModel(root);
        return model;
    }
}
...