繁体   English   中英

如何在我的 Java 拖放应用程序中使按钮可点击和文本字段可编辑?

[英]How to make button clickable and textfield editable in my Java drag and drop app?

我正在学习 Java Swing 中的拖放功能,所以我修改了一个示例应用程序,如下所示:

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.*;
import java.util.Arrays;
import javax.activation.*;
import javax.swing.*;

public class Demo_Drag_And_Drop_Panel extends JPanel
{
  public Demo_Drag_And_Drop_Panel()
  {
    DefaultListModel<Item_Panel> m=new DefaultListModel<>();
    for (String s : Arrays.asList("error","information","question","warning")) m.addElement(new Item_Panel(s));
    JList<Item_Panel> list=new JList<>(m);
    list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    list.setTransferHandler(new ListItem_TransferHandler());
    list.setDropMode(DropMode.INSERT);
    list.setDragEnabled(true);

    list.setLayoutOrientation(JList.HORIZONTAL_WRAP);                          // http://java-swing-tips.blogspot.jp/2008/10/rubber-band-selection-drag-and-drop.html
    list.setVisibleRowCount(0);
    list.setFixedCellWidth(300);
    list.setFixedCellHeight(36);
    list.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
    list.setCellRenderer(new ListCellRenderer<Item_Panel>()
    {
//      private final JPanel p=new JPanel(new BorderLayout());
      private final JPanel p=new JPanel(new FlowLayout(0,1,1));
      JLabel icon=new JLabel((Icon)null,JLabel.CENTER);
      JButton button=new JButton();
      JLabel label=new JLabel();
      JTextField textField=new JTextField();
      
      @Override public Component getListCellRendererComponent(JList list,Item_Panel value,int index,boolean isSelected,boolean cellHasFocus)
      {
        icon.setIcon(value.icon);
        button.setText(value.button.getText());
        button.addMouseListener(new MouseAdapter()
        {
          public void mouseClicked(MouseEvent e)
          {
            if ((e.getModifiers() & InputEvent.BUTTON1_MASK)!=0)
            {
//            Out("mouseClicked : Left");
              Out(value.name);
            }
            else if ((e.getModifiers() & InputEvent.BUTTON2_MASK)!=0)
            {
//            Out("mouseClicked : Middle");
            }
            else if ((e.getModifiers() & InputEvent.BUTTON3_MASK)!=0)
            {
//            Out("mouseClicked : Right");

            }
          }
        });
        label.setText(value.name);
        label.setForeground(isSelected?list.getSelectionForeground():list.getForeground());
        textField.setText(value.textField.getText());
        textField.setEditable(true);
        p.add(icon);
        p.add(button);
        p.add(label);
        p.add(textField);
        p.setBackground(isSelected?list.getSelectionBackground():list.getBackground());
        return p;
      }
    });
    add(new JScrollPane(list));
  }

  private static void out(String message) { System.out.print(message); }
  private static void Out(String message) { System.out.println(message); }

  public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); }

  public static void createAndShowGUI()
  {
    JFrame f=new JFrame("Demo_Drag_And_Drop_Panel");
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new Demo_Drag_And_Drop_Panel());
    f.setSize(350,213);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class Item_Panel
{
  public final String name;
  public final Icon icon;
  public final JButton button;
  public final JTextField textField;
  
  public Item_Panel(String name)
  {
    this.name=name;
    icon=UIManager.getIcon("OptionPane."+name+"Icon");
    button=new JButton(name);
    textField=new JTextField(name);
  }
}
//@camickr already suggested above.
//http://docs.oracle.com/javase/tutorial/uiswing/dnd/dropmodedemo.html

class ListItem_TransferHandler extends TransferHandler
{
  private final DataFlavor localObjectFlavor;
  private Object[] transferedObjects=null;

  public ListItem_TransferHandler() { localObjectFlavor=new ActivationDataFlavor(Object[].class,DataFlavor.javaJVMLocalObjectMimeType,"Array of items"); }

  @SuppressWarnings("deprecation")
  @Override protected Transferable createTransferable(JComponent c)
  {
    JList list=(JList)c;
    indices=list.getSelectedIndices();
    transferedObjects=list.getSelectedValues();
    return new DataHandler(transferedObjects,localObjectFlavor.getMimeType());
  }

  @Override public boolean canImport(TransferSupport info)
  {
    if (!info.isDrop() || !info.isDataFlavorSupported(localObjectFlavor)) return false;
    return true;
  }

  @Override public int getSourceActions(JComponent c)
  {
    return MOVE; //TransferHandler.COPY_OR_MOVE;
  }

  @SuppressWarnings("unchecked")
  @Override public boolean importData(TransferSupport info)
  {
    if (!canImport(info)) return false;
    JList target=(JList)info.getComponent();
    JList.DropLocation dl=(JList.DropLocation)info.getDropLocation();
    DefaultListModel listModel=(DefaultListModel)target.getModel();
    int index=dl.getIndex();
    int max=listModel.getSize();
    if (index<0||index>max) index=max;
    addIndex=index;
    try
    {
      Object[] values=(Object[])info.getTransferable().getTransferData(localObjectFlavor);
      addCount=values.length;
      for (int i=0;i<values.length;i++)
      {
        int idx=index++;
        listModel.add(idx,values[i]);
        target.addSelectionInterval(idx,idx);
      }
      return true;
    }
    catch (UnsupportedFlavorException ufe) { ufe.printStackTrace(); }
    catch (IOException ioe) { ioe.printStackTrace(); }
    return false;
  }

  @Override protected void exportDone(JComponent c,Transferable data,int action) { cleanup(c,action==MOVE); }

  private void cleanup(JComponent c,boolean remove)
  {
    if (remove&&indices!=null)
    {
      JList source=(JList)c;
      DefaultListModel model=(DefaultListModel)source.getModel();
      if (addCount>0)
      {
        //http://java-swing-tips.googlecode.com/svn/trunk/DnDReorderList/src/java/example/MainPanel.java
        for (int i=0;i<indices.length;i++) if (indices[i]>=addIndex) indices[i]+=addCount;
      }
      for (int i=indices.length-1;i>=0;i--)
      {
        model.remove(indices[i]);
      }
    }
    indices=null;
    addCount=0;
    addIndex=-1;
  }
  private int[] indices=null;
  private int addIndex=-1; //Location where items were added
  private int addCount=0;  //Number of items added.
}

但是当我运行它时,我注意到按钮不可点击并且文本字段不可编辑,如何修复它们? 换句话说,我希望能够单击按钮和 output 一些信息并能够单击文本字段并编辑其中的文本,该怎么做?

JList不支持“可食用性”。 渲染只不过是涂在组件表面上的“橡皮图章”。

现在,拖放不是“简单”的 API,它需要一些工作才能使其正常工作(大量的锅炉电镀)

在此处输入图像描述

重要的是,您应该注意拖动组件通常是一个坏主意,您最终会遇到各种奇怪和随机的问题。 相反,您应该专注于传输数据。

因此,在本例中,我将“数据”与“用户界面”分离。 有一个Item (数据),一个ItemPane (数据视图),它被放置在一个可滚动的容器中。

当您“拖动” ItemPane时,首先将其从容器中移除,然后提取并“导出” Item 当您放下它时,会创建一个新的ItemPane并将Item应用于它

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
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.DropTargetContext;
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 java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class Item {
        public final String name;
        public final Icon icon;

        public Item(String name) {
            this.name = name;
            icon = UIManager.getIcon("OptionPane." + name + "Icon");
        }
    }

    public class ItemPane extends JPanel {

        private Item item;

        public ItemPane(Item item) {
            this.item = item;
            setLayout(new FlowLayout(0, 1, 1));
            JLabel icon = new JLabel(item.icon, JLabel.CENTER);
            JButton button = new JButton(item.name);
            JLabel label = new JLabel(item.name);
            JTextField textField = new JTextField(item.name);

            add(icon);
            add(button);
            add(label);
            add(textField);
        }

        public Item getItem() {
            return item;
        }

    }

    public class TestPane extends JPanel {

        public TestPane() {
            JPanel mainPanel = new javax.swing.JPanel();
            mainPanel.setLayout(new GridLayout(4, 0));

            for (String s : Arrays.asList("error","information","question","warning")) {
                ItemPane itemPane = new ItemPane(new Item(s));
                add(itemPane);
                DragDropManager.INSTANCE.installDrag(itemPane);
                mainPanel.add(itemPane);
            }

            DropHandler dropHandler = new DropHandler();
            DropTarget dropTarget = new DropTarget(mainPanel, DnDConstants.ACTION_MOVE, dropHandler, true);
            mainPanel.setDropTarget(dropTarget);

            setLayout(new BorderLayout());
            add(new JScrollPane(mainPanel));
        }

        public enum DragDropManager {

            INSTANCE;

            private Map<ItemPane, DragManager> handlers = new HashMap<>(25);

            protected void installDrag(ItemPane comp) {
                handlers.put(comp, new DragManager(comp));
            }

            protected void uninstallDrag(Component comp) {
                DragManager manager = handlers.remove(comp);
                if (manager != null) {
                    manager.uninstall();
                }
            }

            protected class DragManager {

                DragGestureHandler dragGestureHandler;
                DragGestureRecognizer dgr;

                public DragManager(ItemPane comp) {
                    dragGestureHandler = new DragGestureHandler(comp);
                    dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                            comp,
                            DnDConstants.ACTION_MOVE,
                            dragGestureHandler);
                }

                public void uninstall() {
                    dgr.removeDragGestureListener(dragGestureHandler);
                    dragGestureHandler = null;
                    dgr = null;
                }
            }
        }

        public static class ItemDataFlavor extends DataFlavor {

            // This saves me having to make lots of copies of the same thing
            public static final ItemDataFlavor SHARED = new ItemDataFlavor();

            public ItemDataFlavor() {
                super(Item.class, null);
            }
        }

        public static class ItemTransferable implements Transferable {

            private DataFlavor[] flavors = new DataFlavor[]{ItemDataFlavor.SHARED};
            private Item item;

            public ItemTransferable(Item item) {
                this.item = item;
            }

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

            @Override
            public boolean isDataFlavorSupported(DataFlavor flavor) {
                // Okay, for this example, this is over kill, but makes it easier
                // to add new flavor support by subclassing
                boolean supported = false;
                for (DataFlavor mine : getTransferDataFlavors()) {
                    if (mine.equals(flavor)) {
                        supported = true;
                        break;
                    }
                }

                return supported;
            }

            public Item getItem() {
                return item;
            }

            @Override
            public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
                Object data = null;
                if (isDataFlavorSupported(flavor)) {
                    data = getItem();
                } else {
                    throw new UnsupportedFlavorException(flavor);
                }
                return data;
            }
        }

        public static class DragGestureHandler implements DragGestureListener, DragSourceListener {

            private Container parent;
            private final ItemPane component;

            public DragGestureHandler(ItemPane child) {
                this.component = child;
            }

            public ItemPane getItemPane() {
                return component;
            }

            public Item getItem() {
                return component.getItem();
            }

            public void setParent(Container parent) {
                this.parent = parent;
            }

            public Container getParent() {
                return parent;
            }

            @Override
            public void dragGestureRecognized(DragGestureEvent dge) {
                // Create our transferable wrapper
                Transferable transferable = new ItemTransferable(getItem());

                // Start the "drag" process...
                DragSource ds = dge.getDragSource();
                ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);

                // When the drag begins, we need to grab a reference to the
                // parent container so we can return it if the drop
                // is rejected
                Container parent = getItemPane().getParent();

                setParent(parent);

                // Remove the panel from the parent.  If we don't do this, it
                // can cause serialization issues.  We could over come this
                // by allowing the drop target to remove the component, but that's
                // an argument for another day
                parent.remove(getItemPane());

                // Update the display
                parent.invalidate();
                parent.repaint();


                DragDropManager.INSTANCE.uninstallDrag(getItemPane());
            }

            @Override
            public void dragEnter(DragSourceDragEvent dsde) {
            }

            @Override
            public void dragOver(DragSourceDragEvent dsde) {
            }

            @Override
            public void dropActionChanged(DragSourceDragEvent dsde) {
            }

            @Override
            public void dragExit(DragSourceEvent dse) {
            }

            @Override
            public void dragDropEnd(DragSourceDropEvent dsde) {
                // If the drop was not sucessful, we need to
                // return the component back to it's previous
                // parent
                if (!dsde.getDropSuccess()) {

                    getParent().add(getItemPane());

                    getParent().invalidate();
                    getParent().repaint();

                }
            }
        }

        public class DropHandler implements DropTargetListener {

            private JComponent spacer = new JPanel();

            public DropHandler() {
                spacer.setBackground(Color.RED);
            }

            @Override
            public void dragEnter(DropTargetDragEvent dtde) {
                // Determine if can actual process the contents comming in.
                // You could try and inspect the transferable as well, but 
                // There is an issue on the MacOS under some circumstances
                // where it does not actually bundle the data until you accept the
                // drop.
                if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                    dtde.acceptDrag(DnDConstants.ACTION_MOVE);
                } else {
                    dtde.rejectDrag();
                }
            }

            @Override
            public void dragOver(DropTargetDragEvent dtde) {
                if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                    Point p = dtde.getLocation();
                    DropTargetContext dtc = dtde.getDropTargetContext();
                    Container parent = (Container) dtc.getComponent();
                    Component target = parent.getComponentAt(p);
                    int insertPoint = Math.max(0, parent.getComponentZOrder(target));
                    if (spacer.getParent() == null) {
                        parent.add(spacer, insertPoint);
                    } else {
                        parent.setComponentZOrder(spacer, insertPoint);
                    }
                    parent.revalidate();
                    parent.repaint();

                    Point pic = SwingUtilities.convertPoint(spacer, p, target);
                    Rectangle bounds = spacer.getBounds();
                    bounds.setLocation(pic);

                    ((JComponent) parent).scrollRectToVisible(bounds);
                }
            }

            @Override
            public void dropActionChanged(DropTargetDragEvent dtde) {
            }

            @Override
            public void dragExit(DropTargetEvent dte) {
                Container parent = (Container) dte.getDropTargetContext().getComponent();
                parent.remove(spacer);
                parent.revalidate();
                parent.repaint();
            }

            @Override
            public void drop(DropTargetDropEvent dtde) {
                boolean success = false;

                // Basically, we want to unwrap the present...
                if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                    Transferable transferable = dtde.getTransferable();
                    try {
                        Object data = transferable.getTransferData(ItemDataFlavor.SHARED);
                        if (data instanceof Item) {
                            Item item = (Item) data;

                            DropTargetContext dtc = dtde.getDropTargetContext();
                            Component component = dtc.getComponent();
                            if (component instanceof JComponent) {
                                Container parent = (Container) component;

                                Point p = dtde.getLocation();
                                Component before = parent.getComponentAt(p);
                                int insertPoint = Math.max(0, parent.getComponentZOrder(before));
                                parent.remove(spacer);

                                ItemPane itemPane = new ItemPane(item);
                                parent.add(itemPane, insertPoint);
                                parent.revalidate();
                                parent.repaint();

                                DragDropManager.INSTANCE.installDrag(itemPane);

                                success = true;
                                dtde.acceptDrop(DnDConstants.ACTION_MOVE);

                                invalidate();
                                repaint();
                            } else {
                                success = false;
                                dtde.rejectDrop();
                            }

                        } else {
                            success = false;
                            dtde.rejectDrop();
                        }

                    } catch (Exception exp) {
                        success = false;
                        dtde.rejectDrop();
                        exp.printStackTrace();
                    }
                } else {
                    success = false;
                    dtde.rejectDrop();
                }
                dtde.dropComplete(success);
            }
        }
    }
}

@MadProgrammer:很有趣,我刚刚用 Java 8 尝试了你的修改版本,它编译正常,并且可以运行,但我注意到一些问题:

[1] 关闭应用程序后,进程仍在运行,因此我修复了该问题。

[2] 我添加了一个按钮点击监听器,现在它可以 output 一些信息。

[3] 我尝试更改JTextFiled中的一些文本,然后尝试将更改的项目拖放到$ 下,多次拖放后更改被删除,为什么? 它还能记住变化吗? 毕竟可编辑的 JTextFiled 是用于更改文本的,对吧^_^?,但是,如果更改的字段不是 D&D [其他未更改的项目是 D&D]。 然后它似乎记住了这些变化。

所以,总的来说有改进,但如果我们能修复更改的字段并记住文本更改,那么我会非常高兴。 这是我修改后的代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
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.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.addWindowListener( new WindowAdapter()
                {
                  public void windowActivated(WindowEvent e) { }
                  public void windowClosed(WindowEvent e) { }
                  public void windowClosing(WindowEvent e) { System.exit(0); }
                });
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    class Item {

        public final String name;
        public final Icon icon;

        public Item(String name) {
            this.name = name;
            icon = UIManager.getIcon("OptionPane." + name + "Icon");
        }
    }

    public class ItemPane extends JPanel {

        private Item item;

        public ItemPane(Item item) {
            this.item = item;
            setLayout(new FlowLayout(0, 1, 1));
            JLabel icon = new JLabel(item.icon, JLabel.CENTER);
            JButton button = new JButton(item.name);
            button.addMouseListener(new MouseAdapter()
            {
              public void mouseClicked(MouseEvent e)
              {
                if ((e.getModifiers()&InputEvent.BUTTON1_MASK)!=0)
                {
//          Out("mouseClicked : Left");
                  System.out.println(item.name);
                }
                else if ((e.getModifiers()&InputEvent.BUTTON2_MASK)!=0)
                {
//          Out("mouseClicked : Middle");
                }
                else if ((e.getModifiers()&InputEvent.BUTTON3_MASK)!=0)
                {
//          Out("mouseClicked : Right");
                }
              }
            });
            JLabel label = new JLabel(item.name);
            JTextField textField = new JTextField(item.name);

            add(icon);
            add(button);
            add(label);
            add(textField);
        }

        public Item getItem() {
            return item;
        }

    }

    public class TestPane extends JPanel {

        public TestPane() {
            JPanel mainPanel = new javax.swing.JPanel();
            mainPanel.setLayout(new GridLayout(4, 0));

            for (String s : Arrays.asList("error", "information", "question", "warning")) {
                ItemPane itemPane = new ItemPane(new Item(s));
                add(itemPane);
                DragDropManager.INSTANCE.installDrag(itemPane);
                mainPanel.add(itemPane);
            }

            DropHandler dropHandler = new DropHandler();
            DropTarget dropTarget = new DropTarget(mainPanel, DnDConstants.ACTION_MOVE, dropHandler, true);
            mainPanel.setDropTarget(dropTarget);

            setLayout(new BorderLayout());
            add(new JScrollPane(mainPanel));
        }

    }

    public enum DragDropManager {

        INSTANCE;

        private Map<ItemPane, DragManager> handlers = new HashMap<>(25);

        protected void installDrag(ItemPane comp) {
            handlers.put(comp, new DragManager(comp));
        }

        protected void uninstallDrag(Component comp) {
            DragManager manager = handlers.remove(comp);
            if (manager != null) {
                manager.uninstall();
            }
        }

        protected class DragManager {

            DragGestureHandler dragGestureHandler;
            DragGestureRecognizer dgr;

            public DragManager(ItemPane comp) {
                dragGestureHandler = new DragGestureHandler(comp);
                dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
                        comp,
                        DnDConstants.ACTION_MOVE,
                        dragGestureHandler);
            }

            public void uninstall() {
                dgr.removeDragGestureListener(dragGestureHandler);
                dragGestureHandler = null;
                dgr = null;
            }
        }
    }

    public static class ItemDataFlavor extends DataFlavor {

        // This saves me having to make lots of copies of the same thing
        public static final ItemDataFlavor SHARED = new ItemDataFlavor();

        public ItemDataFlavor() {
            super(Item.class, null);
        }
    }

    public static class ItemTransferable implements Transferable {

        private DataFlavor[] flavors = new DataFlavor[]{ItemDataFlavor.SHARED};
        private Item item;

        public ItemTransferable(Item item) {
            this.item = item;
        }

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

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            // Okay, for this example, this is over kill, but makes it easier
            // to add new flavor support by subclassing
            boolean supported = false;
            for (DataFlavor mine : getTransferDataFlavors()) {
                if (mine.equals(flavor)) {
                    supported = true;
                    break;
                }
            }

            return supported;
        }

        public Item getItem() {
            return item;
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            Object data = null;
            if (isDataFlavorSupported(flavor)) {
                data = getItem();
            } else {
                throw new UnsupportedFlavorException(flavor);
            }
            return data;
        }
    }

    public static class DragGestureHandler implements DragGestureListener, DragSourceListener {

        private Container parent;
        private final ItemPane component;

        public DragGestureHandler(ItemPane child) {
            this.component = child;
        }

        public ItemPane getItemPane() {
            return component;
        }

        public Item getItem() {
            return component.getItem();
        }

        public void setParent(Container parent) {
            this.parent = parent;
        }

        public Container getParent() {
            return parent;
        }

        @Override
        public void dragGestureRecognized(DragGestureEvent dge) {
            // Create our transferable wrapper
            Transferable transferable = new ItemTransferable(getItem());

            // Start the "drag" process...
            DragSource ds = dge.getDragSource();
            ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);

            // When the drag begins, we need to grab a reference to the
            // parent container so we can return it if the drop
            // is rejected
            Container parent = getItemPane().getParent();

            setParent(parent);

            // Remove the panel from the parent.  If we don't do this, it
            // can cause serialization issues.  We could over come this
            // by allowing the drop target to remove the component, but that's
            // an argument for another day
            parent.remove(getItemPane());

            // Update the display
            parent.invalidate();
            parent.repaint();

            DragDropManager.INSTANCE.uninstallDrag(getItemPane());
        }

        @Override
        public void dragEnter(DragSourceDragEvent dsde) {
        }

        @Override
        public void dragOver(DragSourceDragEvent dsde) {
        }

        @Override
        public void dropActionChanged(DragSourceDragEvent dsde) {
        }

        @Override
        public void dragExit(DragSourceEvent dse) {
        }

        @Override
        public void dragDropEnd(DragSourceDropEvent dsde) {
            // If the drop was not sucessful, we need to
            // return the component back to it's previous
            // parent
            if (!dsde.getDropSuccess()) {

                getParent().add(getItemPane());

                getParent().invalidate();
                getParent().repaint();

            }
        }
    }

    public class DropHandler implements DropTargetListener {

        private JComponent spacer = new JPanel();

        public DropHandler() {
            spacer.setBackground(Color.RED);
        }

        @Override
        public void dragEnter(DropTargetDragEvent dtde) {
            // Determine if can actual process the contents comming in.
            // You could try and inspect the transferable as well, but 
            // There is an issue on the MacOS under some circumstances
            // where it does not actually bundle the data until you accept the
            // drop.
            if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                dtde.acceptDrag(DnDConstants.ACTION_MOVE);
            } else {
                dtde.rejectDrag();
            }
        }

        @Override
        public void dragOver(DropTargetDragEvent dtde) {
            if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                Point p = dtde.getLocation();
                DropTargetContext dtc = dtde.getDropTargetContext();
                Container parent = (Container) dtc.getComponent();
                Component target = parent.getComponentAt(p);
                int insertPoint = Math.max(0, parent.getComponentZOrder(target));
                if (spacer.getParent() == null) {
                    parent.add(spacer, insertPoint);
                } else {
                    parent.setComponentZOrder(spacer, insertPoint);
                }
                parent.revalidate();
                parent.repaint();

                Point pic = SwingUtilities.convertPoint(spacer, p, target);
                Rectangle bounds = spacer.getBounds();
                bounds.setLocation(pic);

                ((JComponent) parent).scrollRectToVisible(bounds);
            }
        }

        @Override
        public void dropActionChanged(DropTargetDragEvent dtde) {
        }

        @Override
        public void dragExit(DropTargetEvent dte) {
            Container parent = (Container) dte.getDropTargetContext().getComponent();
            parent.remove(spacer);
            parent.revalidate();
            parent.repaint();
        }

        @Override
        public void drop(DropTargetDropEvent dtde) {
            boolean success = false;

            // Basically, we want to unwrap the present...
            if (dtde.isDataFlavorSupported(ItemDataFlavor.SHARED)) {
                Transferable transferable = dtde.getTransferable();
                try {
                    Object data = transferable.getTransferData(ItemDataFlavor.SHARED);
                    if (data instanceof Item) {
                        Item item = (Item) data;

                        DropTargetContext dtc = dtde.getDropTargetContext();
                        Component component = dtc.getComponent();
                        if (component instanceof JComponent) {
                            Container parent = (Container) component;

                            Point p = dtde.getLocation();
                            Component before = parent.getComponentAt(p);
                            int insertPoint = Math.max(0, parent.getComponentZOrder(before));
                            parent.remove(spacer);

                            ItemPane itemPane = new ItemPane(item);
                            parent.add(itemPane, insertPoint);
                            parent.revalidate();
                            parent.repaint();

                            DragDropManager.INSTANCE.installDrag(itemPane);

                            success = true;
                            dtde.acceptDrop(DnDConstants.ACTION_MOVE);

                            parent.invalidate();
                            parent.repaint();
                        } else {
                            success = false;
                            dtde.rejectDrop();
                        }

                    } else {
                        success = false;
                        dtde.rejectDrop();
                    }

                } catch (Exception exp) {
                    success = false;
                    dtde.rejectDrop();
                    exp.printStackTrace();
                }
            } else {
                success = false;
                dtde.rejectDrop();
            }
            dtde.dropComplete(success);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM