java拖放

java拖放,java,swing,awt,drag-and-drop,Java,Swing,Awt,Drag And Drop,我试图熟悉java中的拖放操作,但我找到的所有教程都是。。。(让我生气) 我只想从JList(包含在名为“UserPanel”的自制JPanel中)中拖动一个“PublicUserLabel”,然后将其放入从JTabbedPanel生成的自制类中。 拖动对象本身而不是其stringrepresentation是非常重要的 这就是我到目前为止所做的: PublicUserLabel public class PublicUserLabel extends JLabel implements Dra

我试图熟悉java中的拖放操作,但我找到的所有教程都是。。。(让我生气)

我只想从JList(包含在名为“UserPanel”的自制JPanel中)中拖动一个“PublicUserLabel”,然后将其放入从JTabbedPanel生成的自制类中。 拖动对象本身而不是其stringrepresentation是非常重要的

这就是我到目前为止所做的: PublicUserLabel

public class PublicUserLabel extends JLabel implements DragSourceListener, DragGestureListener, Transferable
    {
        private DragSource ds;
        private PublicUser user;

        public PublicUserLabel(PublicUser user)
        {
            super(user.getName());
            this.user = user;
            ds = new DragSource();
            ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent e)
        {
            ds.startDrag(e, DragSource.DefaultCopyDrop, this, this);
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException
        {
            if (flavor.equals(PublicUserFlavor.publicUserFlavor))
            {
                return this;//TODO ?
            }
            throw new UnsupportedFlavorException(flavor);
        }

        @Override
        public DataFlavor[] getTransferDataFlavors()
        {
            DataFlavor[] df = new DataFlavor[2];
            df[0] = DataFlavor.stringFlavor;
            df[1] = PublicUserFlavor.publicUserFlavor;
            return df;
        }

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

    //some more methods
    }
用户面板:

public class UserPanel extends JPanel
{
    private JTextField search;
    private List<PublicUser> allUser;
    private JList<PublicUserLabel> list;
    private JScrollPane scrollPane;
    private DefaultListModel<PublicUserLabel> listModel;

    public UserPanel()
    {
        allUser = new LinkedList<PublicUser>();
        listModel = new DefaultListModel<PublicUserLabel>();
        list = new JList<PublicUserLabel>(listModel);
        list.setDragEnabled(true);
选项卡面板:

public class TabPanel extends JTabbedPane implements DropTargetListener
{
    public TabPanel()
    {
        setTabPlacement(JTabbedPane.BOTTOM);
        addNewTabComponent("bla");
        addNewTabComponent("blub");
        setDropTarget(new DropTarget(this, this));
    }

    @Override
    public void drop(DropTargetDropEvent e)
    {
        Transferable transferable = e.getTransferable();
        if (transferable.isDataFlavorSupported(PublicUserFlavor.publicUserFlavor))
        {
            e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            try
            {
                Object o = transferable.getTransferData(PublicUserFlavor.publicUserFlavor);
                System.out.println(o);
                if (o instanceof PublicUserLabel)
                {
                    PublicUserLabel l = (PublicUserLabel)o;
                    PublicUser u = l.getUser();
                    System.out.println(u);
                }
            }
            catch (UnsupportedFlavorException e1)
            {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            catch (IOException e1)
            {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            e.getDropTargetContext().dropComplete(true);
        }
    }
drop方法中有一些syso,如果用户被丢弃在面板中,则应执行这些syso。但事实并非如此。我做错什么了吗?
谢谢你的帮助

我能看到的主要问题是您混合了两种不同的API。您正在使用低级的D'n'D API和较新的“component D'n'D”API

就我个人而言,新的API让我很恼火,所以我倾向于避免使用它

我不明白为什么需要转移标签,而转移底层的
PublicUser
对象会更好,但这只是我的问题

import java.awt.BorderLayout;
import java.awt.EventQueue;
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.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestDnD {

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

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

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

        });
    }

    public class TestPane extends JPanel {

        private JList list;

        public TestPane() {
            setLayout(new BorderLayout());
            list = new JList();
            DefaultListModel model = new DefaultListModel();
            model.addElement(new User("Shaun"));
            model.addElement(new User("Andy"));
            model.addElement(new User("Luke"));
            model.addElement(new User("Han"));
            model.addElement(new User("Liea"));
            model.addElement(new User("Yoda"));
            list.setModel(model);
            add(new JScrollPane(list), BorderLayout.WEST);

            DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                            list,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DragGestureHandler(list));

            JPanel panel = new JPanel(new GridBagLayout());
            add(panel);

            DropTarget dt = new DropTarget(
                            panel,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DropTargetHandler(panel),
                            true);

        }

    }

    public static class User {

        private String name;

        public User(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return name;
        }

    }

    public static class UserTransferable implements Transferable {

        public static final DataFlavor USER_DATA_FLAVOR = new DataFlavor(User.class, "User");
        private User user;

        public UserTransferable(User user) {
            this.user = user;
        }

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

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

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            Object value = null;
            if (USER_DATA_FLAVOR.equals(flavor)) {
                value = user;
            } else {
                throw new UnsupportedFlavorException(flavor);
            }
            return value;
        }

    }

    protected class DragGestureHandler implements DragGestureListener {

        private JList list;

        public DragGestureHandler(JList list) {
            this.list = list;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            Object selectedValue = list.getSelectedValue();
            if (selectedValue instanceof User) {
                User user = (User) selectedValue;
                Transferable t = new UserTransferable(user);
                DragSource ds = dge.getDragSource();
                ds.startDrag(
                                dge,
                                null,
                                t,
                                new DragSourceHandler());
            }

        }

    }

    protected class DragSourceHandler implements DragSourceListener {

        public void dragEnter(DragSourceDragEvent dsde) {
        }

        public void dragOver(DragSourceDragEvent dsde) {
        }

        public void dropActionChanged(DragSourceDragEvent dsde) {
        }

        public void dragExit(DragSourceEvent dse) {
        }

        public void dragDropEnd(DragSourceDropEvent dsde) {

            System.out.println("Drag ended...");

        }

    }

    protected class DropTargetHandler implements DropTargetListener {

        private JPanel panel;

        public DropTargetHandler(JPanel panel) {
            this.panel = panel;
        }

        public void dragEnter(DropTargetDragEvent dtde) {
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                System.out.println("Accept...");
                dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
            } else {
                System.out.println("Drag...");
                dtde.rejectDrag();
            }
        }

        public void dragOver(DropTargetDragEvent dtde) {
        }

        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        public void dragExit(DropTargetEvent dte) {
        }

        public void drop(DropTargetDropEvent dtde) {
            System.out.println("Dropped...");
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                Transferable t = dtde.getTransferable();
                if (t.isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                    try {
                        Object transferData = t.getTransferData(UserTransferable.USER_DATA_FLAVOR);
                        if (transferData instanceof User) {
                            User user = (User) transferData;
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            panel.add(new JLabel(user.getName()));
                            panel.revalidate();
                            panel.repaint();
                        } else {
                            dtde.rejectDrop();
                        }
                    } catch (UnsupportedFlavorException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    }
                } else {
                    dtde.rejectDrop();
                }
            }
        }

    }

}


我能看到的主要问题是,您混合了两种不同的API。您正在使用低级的D'n'D API和较新的“component D'n'D”API

就我个人而言,新的API让我很恼火,所以我倾向于避免使用它

我不明白为什么需要转移标签,而转移底层的
PublicUser
对象会更好,但这只是我的问题

import java.awt.BorderLayout;
import java.awt.EventQueue;
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.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestDnD {

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

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

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

        });
    }

    public class TestPane extends JPanel {

        private JList list;

        public TestPane() {
            setLayout(new BorderLayout());
            list = new JList();
            DefaultListModel model = new DefaultListModel();
            model.addElement(new User("Shaun"));
            model.addElement(new User("Andy"));
            model.addElement(new User("Luke"));
            model.addElement(new User("Han"));
            model.addElement(new User("Liea"));
            model.addElement(new User("Yoda"));
            list.setModel(model);
            add(new JScrollPane(list), BorderLayout.WEST);

            DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                            list,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DragGestureHandler(list));

            JPanel panel = new JPanel(new GridBagLayout());
            add(panel);

            DropTarget dt = new DropTarget(
                            panel,
                            DnDConstants.ACTION_COPY_OR_MOVE,
                            new DropTargetHandler(panel),
                            true);

        }

    }

    public static class User {

        private String name;

        public User(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return name;
        }

    }

    public static class UserTransferable implements Transferable {

        public static final DataFlavor USER_DATA_FLAVOR = new DataFlavor(User.class, "User");
        private User user;

        public UserTransferable(User user) {
            this.user = user;
        }

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

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

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            Object value = null;
            if (USER_DATA_FLAVOR.equals(flavor)) {
                value = user;
            } else {
                throw new UnsupportedFlavorException(flavor);
            }
            return value;
        }

    }

    protected class DragGestureHandler implements DragGestureListener {

        private JList list;

        public DragGestureHandler(JList list) {
            this.list = list;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            Object selectedValue = list.getSelectedValue();
            if (selectedValue instanceof User) {
                User user = (User) selectedValue;
                Transferable t = new UserTransferable(user);
                DragSource ds = dge.getDragSource();
                ds.startDrag(
                                dge,
                                null,
                                t,
                                new DragSourceHandler());
            }

        }

    }

    protected class DragSourceHandler implements DragSourceListener {

        public void dragEnter(DragSourceDragEvent dsde) {
        }

        public void dragOver(DragSourceDragEvent dsde) {
        }

        public void dropActionChanged(DragSourceDragEvent dsde) {
        }

        public void dragExit(DragSourceEvent dse) {
        }

        public void dragDropEnd(DragSourceDropEvent dsde) {

            System.out.println("Drag ended...");

        }

    }

    protected class DropTargetHandler implements DropTargetListener {

        private JPanel panel;

        public DropTargetHandler(JPanel panel) {
            this.panel = panel;
        }

        public void dragEnter(DropTargetDragEvent dtde) {
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                System.out.println("Accept...");
                dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
            } else {
                System.out.println("Drag...");
                dtde.rejectDrag();
            }
        }

        public void dragOver(DropTargetDragEvent dtde) {
        }

        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        public void dragExit(DropTargetEvent dte) {
        }

        public void drop(DropTargetDropEvent dtde) {
            System.out.println("Dropped...");
            if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                Transferable t = dtde.getTransferable();
                if (t.isDataFlavorSupported(UserTransferable.USER_DATA_FLAVOR)) {
                    try {
                        Object transferData = t.getTransferData(UserTransferable.USER_DATA_FLAVOR);
                        if (transferData instanceof User) {
                            User user = (User) transferData;
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            panel.add(new JLabel(user.getName()));
                            panel.revalidate();
                            panel.repaint();
                        } else {
                            dtde.rejectDrop();
                        }
                    } catch (UnsupportedFlavorException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        dtde.rejectDrop();
                    }
                } else {
                    dtde.rejectDrop();
                }
            }
        }

    }

}


在线教程有什么问题?拖动对象本身而不是其stringrepresentation非常重要1)为什么?2) 如果从
JList
开始拖动,将很困难,因为
JList
甚至不包含该
JLabel
,只有呈现的版本才重要,因为用户不仅有名称。用户还具有公共rsa密钥和uuid。我必须至少从丢弃的对象中获取uuid和密钥。我与PublicUser存储了一个列表,其中包含我需要的所有信息,因此我不必使用JList。一个糟糕教程的例子是标题“将所有内容放在一起”。绝对不是所有人都在一起。甚至一个被覆盖的方法的签名也丢失了。@zachlatta在线教程是矛盾的。除非你知道你在看什么。通常,Swing中有两个不同的d'n'd API。有低级API和较新的“组件”API。没有多少教程公开解释他们使用的是哪一个,这使得已经是一个困难的主题变得更加复杂-我知道编写好的教程是一项艰苦的工作-如果艰苦的工作没有达到你想要的结果,你可能会考虑雇佣一个私人导师…在线教程有什么不对?重要的是拖动对象本身而不是它的字符串表示1)为什么?2) 如果从
JList
开始拖动,将很困难,因为
JList
甚至不包含该
JLabel
,只有呈现的版本才重要,因为用户不仅有名称。用户还具有公共rsa密钥和uuid。我必须至少从丢弃的对象中获取uuid和密钥。我与PublicUser存储了一个列表,其中包含我需要的所有信息,因此我不必使用JList。一个糟糕教程的例子是标题“将所有内容放在一起”。绝对不是所有人都在一起。甚至一个被覆盖的方法的签名也丢失了。@zachlatta在线教程是矛盾的。除非你知道你在看什么。通常,Swing中有两个不同的d'n'd API。有低级API和较新的“组件”API。不是很多的教程公开解释他们正在使用的是什么,它使已经是一个困难的主题变得更复杂了——要学好好的教程是很难的。如果你的努力没有得到你想要的结果,你可能会考虑雇佣一个私人导师……失踪或混合你的小天使?-)我认为较新的api更易于使用——遗憾的是,它很难用没有api的组件实现default@kleopatra嗯?什么较新的API?@andrewhompson设置setDrageEnabled/setTransferHandler时钩住的部分,即一些组件(如tree/table/list…)的底层(package.dnd)之上的抽象…:-)@正如你所说,如果它没有内置在组件中,那就是一种痛苦。我还发现,它故意禁用API的某些部分,以至于其他开发人员无法重新引入它们,例如拖动光标/图像。我一直想实现博客中的一些想法,但还没有找到时间坐下来做它——又是你的小天使?——就我个人而言,我认为新的api更容易使用——遗憾的是,它很难用没有它的组件实现default@kleopatra嗯?什么较新的API?@andrewhompson设置setDrageEnabled/setTransferHandler时钩住的部分,即一些组件(如tree/table/list…)的底层(package.dnd)之上的抽象…:-)@正如你所说,如果它没有内置在组件中,那就是一种痛苦。我还发现,它故意禁用API的某些部分,以至于其他开发人员无法重新引入它们,例如拖动光标/图像。我想实现博客中的一些想法,但还没有找到时间坐下来做