8

カスタムオブジェクトのArrayListを含むJListがあり、フィールドへのドラッグアンドドロップを作成しようとしています。Transferableでオブジェクトをパッケージ化して受け取る方法を理解するのに問題があります。

これは私が得た限りです:

import java.awt.*;

import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

public class FlightProjectInterface extends JFrame{

    //create GUI Objects

    private JFrame primaryFrame;
    private JPanel createFlightPanel;
    private JPanel aircraftLayout;

    private JList personsJList, personsOnFlightJList;
    private JTextField pilotLabel, coPilotLabel, backseat1Label, backseat2Label;

    public FlightProjectInterface(){

        //establish frame
        super("Create Flight");
        setLayout( new FlowLayout());

        //aircraftPanel
        aircraftLayout = new JPanel();
        aircraftLayout.setLayout(new GridLayout(2,2));
        pilotLabel = new JTextField("Drag Pilot Here");

        //build person load list
        DefaultListModel listModel = new DefaultListModel();
        for (Person person : Database.persons)
            listModel.addElement(person);

        personsJList = new JList(listModel);
        personsJList.setVisibleRowCount(5);
        personsJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        personsJList.setDragEnabled(true);

        add( new JScrollPane(personsJList) );

        aircraftLayout.add(pilotLabel);
        add(aircraftLayout);

    }//end constructor

}

明確化:JListからオブジェクトを選択し、そこからTransferableを作成するのに問題があります。上記のコードでは、オブジェクトのtoString表現がテキストフィールドに貼り付けられているだけなので、ドロップされた場所からオブジェクトデータをプルすることはできません。オブジェクト自体を「パッケージ化」して、GUIからオブジェクト自体を参照できるプレースホルダーにドロップするにはどうすればよいですか?

理想的には、ドロップできるオブジェクトがそれぞれに含まれる4つのフィールドがあります。削除された場合はリストから削除されますが、置き換えられた場合はリストに戻ります。

4

1 に答える 1

16

ドラッグアンドドロップは複雑な獣になる可能性があり、利用可能な矛盾する情報によって簡単になることはありません。個人的には、Transfer APIを避けたいのですが、私はそのような古い学校です。

DnDへの接着剤は本当にですDataFlavor。私は自分で転がることを好み、人生をずっと楽にしてくれます。

この例では、1つを使用しましたTransferHandlerが、実際には、ドラッグ用とドロップ用に1つずつ必要です。特に、ドロップするコンポーネントごとに1つ必要です。

これの主な理由は、canImportあなたが上にドラッグした場合にそれを拒否するために私のメソッドにトラップを入れたJListので、あなたはそれをにドロップすることしかできませんJLabel、これは少しハックであり、おそらく最良のアイデアではありません。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.io.IOException;

import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DnDTransferableTest {

    public static void main(String[] args) {
        new DnDTransferableTest();
    }

    public DnDTransferableTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    @SuppressWarnings("serial")
    public class TestPane extends JPanel {

        private JList<ListItem> list;
        private JLabel label;

        public TestPane() {

            list = new JList<ListItem>();
            list.setDragEnabled(true);
            list.setTransferHandler(new ListTransferHandler());

            DefaultListModel<ListItem> model = new DefaultListModel<ListItem>();
            for (int index = 0; index < 10; index++) {

                model.addElement(new ListItem("Item " + index));

            }
            list.setModel(model);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 1;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.BOTH;
            add(new JScrollPane(list), gbc);

            label = new JLabel("Drag on me...");
            gbc.gridx++;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.NONE;
            add(label, gbc);

            label.setTransferHandler(new ListTransferHandler());

        }
    }

    @SuppressWarnings("serial")
    public class ListTransferHandler extends TransferHandler {

        @Override
        public boolean canImport(TransferSupport support) {
            return (support.getComponent() instanceof JLabel) && support.isDataFlavorSupported(ListItemTransferable.LIST_ITEM_DATA_FLAVOR);
        }

        @Override
        public boolean importData(TransferSupport support) {
            boolean accept = false;
            if (canImport(support)) {
                try {
                    Transferable t = support.getTransferable();
                    Object value = t.getTransferData(ListItemTransferable.LIST_ITEM_DATA_FLAVOR);
                    if (value instanceof ListItem) {
                        Component component = support.getComponent();
                        if (component instanceof JLabel) {
                            ((JLabel)component).setText(((ListItem)value).getText());
                            accept = true;
                        }
                    }
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
            return accept;
        }

        @Override
        public int getSourceActions(JComponent c) {
            return DnDConstants.ACTION_COPY_OR_MOVE;
        }

        @Override
        protected Transferable createTransferable(JComponent c) {
            Transferable t = null;
            if (c instanceof JList) {
                @SuppressWarnings("unchecked")
                JList<ListItem> list = (JList<ListItem>) c;
                Object value = list.getSelectedValue();
                if (value instanceof ListItem) {
                    ListItem li = (ListItem) value;
                    t = new ListItemTransferable(li);
                }
            }
            return t;
        }

        @Override
        protected void exportDone(JComponent source, Transferable data, int action) {
            System.out.println("ExportDone");
            // Here you need to decide how to handle the completion of the transfer,
            // should you remove the item from the list or not...
        }
    }

    public static class ListItemTransferable implements Transferable {

        public static final DataFlavor LIST_ITEM_DATA_FLAVOR = new DataFlavor(ListItem.class, "java/ListItem");
        private ListItem listItem;

        public ListItemTransferable(ListItem listItem) {
            this.listItem = listItem;
        }

        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{LIST_ITEM_DATA_FLAVOR};
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return flavor.equals(LIST_ITEM_DATA_FLAVOR);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {

            return listItem;

        }
    }

    public static class ListItem {

        private String text;

        public ListItem(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        @Override
        public String toString() {
            return getText();
        }
    }
}
于 2012-12-13T08:55:47.367 に答える