从JTable拖放到JLayeredPane

问题描述:

如何在 JTable JLayeredPane 之间创建拖放.

How to create Drag and drop between JTable and JLayeredPane.

有没有人知道如何实现这一目标?

Does anyone have any ideas how to implement this?

我需要通过拖放在JTable和JLayeredPane之间传输对象.

您必须至少做几件事才能使它起作用:

You have to do a few things at minimum to get this to work:

  • 在您的JTable实例上调用setDragEnabled(true)
  • 设置JTableJLayeredPane
  • Call setDragEnabled(true) on your JTable instance
  • Set the JTables and JLayeredPanes DropTarget
  • Create a draggable Component to add to the JLayeredPane

要设置Component s DropTarget,请调用setDropTarget(DropTarget d)方法并传递一个匿名内部类作为参数.删除 Transferable 的代码> s到Component的数据应该位于drop(DropTargetDropEvent dtde)方法中.

To set a Components DropTarget, call the setDropTarget(DropTarget d) method and pass an anonymous inner class as the argument. Code that drops the Transferables data into the Component should be located in the drop(DropTargetDropEvent dtde) method.

下面的代码片段显示了如何接收Transferable并将其插入到发起放置的JTable行中:

The below snippet shows how to receive a Transferable and insert it into the row of a JTable where the drop was initiated:

table.setDropTarget(new DropTarget() {

    @Override
    public synchronized void drop(DropTargetDropEvent dtde) {
        try {
            // get row to put new item in
            int row = table.rowAtPoint(dtde.getLocation());
            // inserting row:
            ((DefaultTableModel) table.getModel()).insertRow(
                    //if the row wasn't found, add it to the end of the JTable
                    row == -1 ? table.getRowCount() : row,
                    // pass string flavor of transferable data as row data parameter
                    new Object[] {dtde.getTransferable()
                                .getTransferData(DataFlavor.stringFlavor)});
        } catch(UnsupportedFlavorException | IOException e) {
            e.printStackTrace();
        }
    }
});

下面的代码片段再次接收到Transferable,但是将其添加到JLayeredPane的末尾.请注意,因为我为JLayeredPane分配了BoxLayout(SwingConstants.VERTICAL),所以组件被添加到了JLayeredPane的末尾.

This below snippet again receives a Transferable but instead adds it to the end of a JLayeredPane. Note that components are added to the end of the JLayeredPane because I assign a BoxLayout(SwingConstants.VERTICAL) to it.

layeredPane.setDropTarget(new DropTarget() {

    @Override
    public synchronized void drop(DropTargetDropEvent dtde) {
        try {
            // create draggable label to add to layered pane 
            // creating this class will be explained next
            final DraggableLabel label = new DraggableLabel(
                    (String) dtde.getTransferable()
                    .getTransferData(DataFlavor.stringFlavor));

            // add label to layered pane
            layeredPane.add(label, JLayeredPane.DEFAULT_LAYER);
            layeredPane.revalidate();
            layeredPane.repaint();
        } catch(UnsupportedFlavorException | IOException e) {
            e.printStackTrace();
        }
    }

});


要创建可拖动的Component(在本示例中为JLabel),您必须:


To create a draggable Component (In this example a JLabel), you must:

  • 创建一个新的类,该类extends JLabelimplements DragGestureListener DragSourceListener
  • 覆盖所有必需的方法
  • 在构造函数中:
    • Create a new class that extends JLabel and implements DragGestureListener and DragSourceListener
    • Override all the necessary methods
    • In the constructor:
      • Create a new DragSource
      • Create a DragGestureRecognizer and assign it to this the JLabel subclass and this the DragGestureListener

      class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
      
          private DragSource dragSource;
      
          DraggableLabel(String text) {
              super(text);
      
              // create the drag source
              dragSource = new DragSource();
              // assign this component a DragGestureRecognizer
              dragSource.createDefaultDragGestureRecognizer(
                      this, DnDConstants.ACTION_COPY_OR_MOVE, this);
      
              // for contrast with other items in layered pane
              setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
          }
      
          @Override
          public void dragGestureRecognized(DragGestureEvent evt) {
              dragSource.startDrag(
                      evt, //trigger event
                      DragSource.DefaultMoveDrop, // icon
                      new StringSelection(getText()), // transferable data
                      this); // this the DragSourceListener
          }
      
          @Override
          public void dragEnter(DragSourceDragEvent evt) {}
      
          @Override
          public void dragOver(DragSourceDragEvent evt) {}
      
          @Override
          public void dragExit(DragSourceEvent evt) {}
      
          @Override
          public void dropActionChanged(DragSourceDragEvent evt) {}
      
          @Override
          public void dragDropEnd(DragSourceDropEvent evt) {}
      
      }
      


      完整的示例:


      Full working example:

      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Dimension;
      import java.awt.EventQueue;
      import java.awt.datatransfer.DataFlavor;
      import java.awt.datatransfer.StringSelection;
      import java.awt.datatransfer.UnsupportedFlavorException;
      import java.awt.dnd.DnDConstants;
      import java.awt.dnd.DragGestureEvent;
      import java.awt.dnd.DragGestureListener;
      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.DropTargetDropEvent;
      import java.io.IOException;
      import javax.swing.BorderFactory;
      import javax.swing.BoxLayout;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JLayeredPane;
      import javax.swing.JTable;
      import javax.swing.WindowConstants;
      import javax.swing.table.DefaultTableModel;
      
      class DragDropExample {
      
          public static void main(String[] args) {
              EventQueue.invokeLater(() -> {
                  final JFrame frame = new JFrame("JLabel Text Example");
      
                  final JTable table = new JTable(new DefaultTableModel(
                          new Object[][] {
                                  {"Item 1"},
                                  {"Item 2"},
                                  {"Item 3"},
                                  {"Item 4"},
                                  {"Item 5"}},
                          new String[] {"Column Name"}));
                  table.setDragEnabled(true);
                  table.setDropTarget(new DropTarget() {
      
                      @Override
                      public synchronized void drop(DropTargetDropEvent dtde) {
                          try {
                              // get row to put new item in
                              int row = table.rowAtPoint(dtde.getLocation());
                              // inserting row:
                              ((DefaultTableModel) table.getModel()).insertRow(
                                      //if the row wasn't found, add it to the end of the JTable
                                      row == -1 ? table.getRowCount() : row,
                                      // pass string flavor of transferable data as row data parameter
                                      new Object[] {dtde.getTransferable()
                                              .getTransferData(DataFlavor.stringFlavor)});
                          } catch(UnsupportedFlavorException | IOException e) {
                              e.printStackTrace();
                          }
                      }
                  });
      
                  final JLayeredPane layeredPane = new JLayeredPane() {
      
                      @Override
                      public Dimension getPreferredSize() {
                          return new Dimension(200, 300);
                      }
      
                  };
                  layeredPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
                  layeredPane.setLayout(new BoxLayout(layeredPane, BoxLayout.Y_AXIS));
                  layeredPane.setDropTarget(new DropTarget() {
      
                      @Override
                      public synchronized void drop(DropTargetDropEvent dtde) {
                          try {
                              // create draggable label to add to layered pane
                              // creating this class will be explained next
                              final DraggableLabel label = new DraggableLabel(
                                      (String) dtde.getTransferable()
                                              .getTransferData(DataFlavor.stringFlavor));
      
                              // add label to layered pane
                              layeredPane.add(label, JLayeredPane.DEFAULT_LAYER);
                              layeredPane.revalidate();
                              layeredPane.repaint();
                          } catch(UnsupportedFlavorException | IOException e) {
                              e.printStackTrace();
                          }
                      }
      
                  });
      
                  frame.getContentPane().add(table, BorderLayout.WEST);
                  frame.getContentPane().add(layeredPane);
                  frame.pack();
                  frame.setLocationByPlatform(true);
                  frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                  frame.setVisible(true);
              });
          }
      
          static class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
      
              private DragSource dragSource;
      
              DraggableLabel(String text) {
                  super(text);
      
                  // create the drag source
                  dragSource = new DragSource();
                  // assign this component a DragGestureRecognizer
                  dragSource.createDefaultDragGestureRecognizer(
                          this, DnDConstants.ACTION_COPY_OR_MOVE, this);
      
                  // for contrast with other items
                  setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
              }
      
              @Override
              public void dragGestureRecognized(DragGestureEvent evt) {
                  dragSource.startDrag(
                          evt, //trigger event
                          DragSource.DefaultMoveDrop,
                          new StringSelection(getText()),
                          this);
              }
      
              @Override
              public void dragEnter(DragSourceDragEvent evt) {}
      
              @Override
              public void dragOver(DragSourceDragEvent evt) {}
      
              @Override
              public void dragExit(DragSourceEvent evt) {}
      
              @Override
              public void dropActionChanged(DragSourceDragEvent evt) {}
      
              @Override
              public void dragDropEnd(DragSourceDropEvent evt) {}
      
          }
      
      }