最近实现了一个封装后的支持拖拽排序的JList,以下为源代码
重点关注三点:
1、定义拖拽源
2、定义放置目标
3、定义数据传输格式
其中拖起源定义(DragSource)见37-38行,分别定义支持拖拽的组件,拖拽类型以及拖拽监听器定义放置目标(DropTarget)见39行,分别定义接受拖拽的组件以及对应drop监听
数据传输格式(Transferable)见47行,定义拖拽过程中数据传输类型,此处为自定义的数据传输对象ReportObjTransferable,具体参见下方代码
1 public class ReorderableList extends JList 2 implements 3 DragSourceListener, 4 DropTargetListener, 5 DragGestureListener { 6 7 private static final long serialVersionUID = -961840807598972987L; 8 /** 9 * 拖源 10 */ 11 DragSource dragSource; 12 /** 13 * 放置目标 14 */ 15 DropTarget dropTarget; 16 /** 17 * 放置对象 18 */ 19 Object dropTargetCell; 20 /** 21 * 被拖对象index 22 */ 23 int draggedIndex = -1; 24 25 26 /** 27 * 获取放置对象 28 * 29 * @return 30 */ 31 public Object getDropTargetCell() { 32 return dropTargetCell; 33 } 34 35 public ReportReorderableList() { 36 super(); 37 dragSource = DragSource.getDefaultDragSource(); 38 dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); 39 dropTarget = new DropTarget(this, this); 40 } 41 42 public void dragGestureRecognized(DragGestureEvent dge) { 43 Point clickPoint = dge.getDragOrigin(); 44 int index = locationToIndex(clickPoint); 45 if (index == -1) return; 46 Object target = getModel().getElementAt(index); 47 Transferable trans = new ReportObjTransferable(target); 48 draggedIndex = index; 49 dragSource.startDrag(dge, Cursor.getDefaultCursor(), trans, this); 50 } 51 52 public void dragEnter(DropTargetDragEvent dtde) { 53 if (dtde.getSource() != dropTarget) 54 dtde.rejectDrag(); 55 else { 56 dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); 57 } 58 } 59 60 public void dragOver(DropTargetDragEvent dtde) { 61 62 if (dtde.getSource() != dropTarget) dtde.rejectDrag(); 63 // 拿到拖放的目标位置 64 Point dragPoint = dtde.getLocation(); 65 int index = locationToIndex(dragPoint); 66 if (index == -1) 67 dropTargetCell = null; 68 else 69 dropTargetCell = getModel().getElementAt(index); 70 repaint(); 71 } 72 73 public void dropActionChanged(DropTargetDragEvent dtde) {} 74 75 public void dragExit(DropTargetEvent dte) {} 76 77 public void drop(DropTargetDropEvent dtde) { 78 if (dtde.getSource() != dropTarget) { 79 dtde.rejectDrop(); 80 return; 81 } 82 Point dropPoint = dtde.getLocation(); 83 int index = locationToIndex(dropPoint); 84 boolean dropped = false; 85 try { 86 DefaultListModel mod = (DefaultListModel) getModel(); 87 Object dragged = dtde.getTransferable().getTransferData(ReportDataFlavor.localObjectFlavor); 88 // 判断拖拽的对象是否在JList内以及是否已含有当前拖拽对象,不满足条件则不允许放置 89 if ((index == -1 && mod.size()>0) || (index == draggedIndex && index!=-1) || (draggedIndex == -1 && mod.contains(dragged))) { 90 dtde.rejectDrop(); 91 return; 92 } 93 dtde.acceptDrop(DnDConstants.ACTION_MOVE); 94 // 不是从当前面板拖拽的对象,则添加 95 if (draggedIndex == -1) { 96 mod.add(mod.getSize(), dragged); 97 } else { 98 // 从当前面板拖拽的对象,则进行顺序调整 99 boolean sourceBeforeTarget = (draggedIndex < index); 100 mod.remove(draggedIndex); 101 mod.add((sourceBeforeTarget ? index - 1 : index), dragged); 102 } 103 dropped = true; 104 } catch (Exception e) { 105 e.printStackTrace(); 106 } 107 dtde.dropComplete(dropped); 108 } 109 110 public void add(Object obj){ 111 DefaultListModel mod = (DefaultListModel) getModel(); 112 mod.addElement(obj); 113 } 114 115 public void dragEnter(DragSourceDragEvent dsde) {} 116 117 public void dragOver(DragSourceDragEvent dsde) {} 118 119 public void dropActionChanged(DragSourceDragEvent dsde) {} 120 121 public void dragExit(DragSourceEvent dse) {} 122 123 public void dragDropEnd(DragSourceDropEvent dsde) { 124 dropTargetCell = null; 125 draggedIndex = -1; 126 repaint(); 127 } 128 129 130 }
1 public class ReportObjTransferable implements Transferable { 2 Object object; 3 static DataFlavor[] supportedFlavors = {ReportDataFlavor.localObjectFlavor}; 4 5 public ReportObjTransferable(Object obj) { 6 this.object = obj; 7 } 8 9 public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException { 10 if (isDataFlavorSupported(df)) 11 return object; 12 else 13 throw new UnsupportedFlavorException(df); 14 } 15 16 public boolean isDataFlavorSupported(DataFlavor df) { 17 return (df.equals(ReportDataFlavor.localObjectFlavor)); 18 } 19 20 public DataFlavor[] getTransferDataFlavors() { 21 return supportedFlavors; 22 } 23 24 }
1 public class ReportDataFlavor { 2 /** 3 * swing控件 4 */ 5 public static DataFlavor componentFlavor = createConstant(JComponent.class, 6 JComponent.class.getName());11 /** 12 * 本地对象类型 13 */ 14 public static DataFlavor localObjectFlavor = createConstant(DataFlavor.javaJVMLocalObjectMimeType); 15 16 17 /** 18 * 数据类型构造 19 * 20 * @param rc 21 * @param prn 22 * @return 23 */ 24 static private DataFlavor createConstant(Class rc, String prn) { 25 try { 26 return new DataFlavor(rc, prn); 27 } catch (Exception e) { 28 e.printStackTrace(); 29 return null; 30 } 31 } 32 33 static private DataFlavor createConstant(String mimeType) { 34 try { 35 return new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType); 36 } catch (ClassNotFoundException cnfe) { 37 cnfe.printStackTrace(); 38 return null; 39 } 40 } 41 }