drag and drop files from OS into JTable java

后端 未结 1 677
遥遥无期
遥遥无期 2020-12-18 16:54

Can someone show me what I\'m doing wrong? I was able to get drag and drop working with a regular panel but now trying with a table and I can\'t sort it out. I\'m getting co

1条回答
  •  有刺的猬
    2020-12-18 17:20

    I personally would ditch the drop target on the scroll pane, it's going to cause you to many problems.

    Your drop method is a little queezy...

    This is a bad idea....

    List fileList = null;
    try {
        fileList = (List) t
            .getTransferData(DataFlavor.javaFileListFlavor);
    } catch (UnsupportedFlavorException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    File f = (File) fileList.get(0);
    table.setValueAt(f.getAbsolutePath(), row, column);
    table.setValueAt(f.length(), row, column + 1);
    

    Basically, you try and extract the file list from the transferable, and regardless of the success of the operation, you try and use it ?! You do no validation of the returned value at all...

    Your drop code generally doesn't really care about what column the drop occurred on, as you have name and size columns already, so I'd actually ignore that altogether.

    As for the row, now you have two choices. Either you add a new row when the user doesn't drop on an existing one or you reject the attempt.

    Reject drag's "outside" of table

    (Or reject drags that don't call over an existing row)

    To reject the operation while the user is dragging, you need to override the dragOver method...

    @Override
    public synchronized void dragOver(DropTargetDragEvent dtde) {
        Point point = dtde.getLocation();
        int row = table.rowAtPoint(point);
        if (row < 0) {
            dtde.rejectDrag();
            table.clearSelection();
        } else {
            dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
            table.setRowSelectionInterval(row, row);
        }
    }
    

    Now, I'm been a little smart here (and not in the clever way). Basically, if the user has dragged over a row, I've highlighted it. This makes it a little more obvious where the drop is going.

    In your drop method, I would also make some additional checks...

    @Override
    public synchronized void drop(DropTargetDropEvent dtde) {    
        Point point = dtde.getLocation();
        int row = table.rowAtPoint(point);
        if (row >= 0) {
            if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                Transferable t = dtde.getTransferable();
                List fileList = null;
                try {
                    fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                    if (fileList.size() > 0) {
                        table.clearSelection();
                        Point point = dtde.getLocation();
                        int row = table.rowAtPoint(point);
                        DefaultTableModel model = (DefaultTableModel) table.getModel();
                        model.setValueAt(f.getAbsolutePath(), row, 0);
                        model.setValueAt(f.length(), row, 2);
                    }
                } catch (UnsupportedFlavorException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                dtde.rejectDrop();
            }
        } else {
            dtde.rejectDrop();
        }
    }
    

    Accept Drag's "outside" of the table

    The process is relativly the same, except now we can throw away the conditions that would have otherwise caused us to reject the drag/drop (obviously)

    @Override
    public synchronized void dragOver(DropTargetDragEvent dtde) {
        Point point = dtde.getLocation();
        int row = table.rowAtPoint(point);
        if (row < 0) {
            table.clearSelection();
        } else {
            table.setRowSelectionInterval(row, row);
        }
        dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
    }
    

    And the drop method

    @Override
    public synchronized void drop(DropTargetDropEvent dtde) {    
        if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            Transferable t = dtde.getTransferable();
            List fileList = null;
            try {
                fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                if (fileList.size() > 0) {
                    table.clearSelection();
                    Point point = dtde.getLocation();
                    int row = table.rowAtPoint(point);
                    DefaultTableModel model = (DefaultTableModel) table.getModel();
                    for (Object value : fileList) {
                        if (value instanceof File) {
                            File f = (File) value;
                            if (row < 0) {
                                System.out.println("addRow");
                                model.addRow(new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});
                            } else {
                                System.out.println("insertRow " + row);
                                model.insertRow(row, new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});
                                row++;
                            }
                        }
                    }
                }
            } catch (UnsupportedFlavorException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            dtde.rejectDrop();
        }
    }
    

    Note. This will insert rows at the drop point, push all the existing rows down OR if not dropped on an existing row, will add them to the end...

    TEST CODE

    This a full running example I used to test the code...

    public class DropTable {
    
        public static void main(String[] args) {
            new DropTable();
        }
    
        public DropTable() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new DropPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
    
            });
        }
    
        public class DropPane extends JPanel {
    
            private JTable table;
            private JScrollPane scroll;
            private DefaultTableModel tm = new DefaultTableModel(new String[]{"File", "File Type", "Size", "Status"}, 0);
    
            public DropPane() {
                table = new JTable();
                table.setShowGrid(true);
                table.setShowHorizontalLines(true);
                table.setShowVerticalLines(true);
                table.setGridColor(Color.GRAY);
    
                table.setModel(tm);
                table.setFillsViewportHeight(true);
                table.setPreferredSize(new Dimension(500, 300));
    
                scroll = new JScrollPane(table);
    
                table.setDropTarget(new DropTarget() {
                    @Override
                    public synchronized void dragOver(DropTargetDragEvent dtde) {
                        Point point = dtde.getLocation();
                        int row = table.rowAtPoint(point);
                        if (row < 0) {
                            table.clearSelection();
                        } else {
                            table.setRowSelectionInterval(row, row);
                        }
                        dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
                    }
    
                    @Override
                    public synchronized void drop(DropTargetDropEvent dtde) {
                        if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                            dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                            Transferable t = dtde.getTransferable();
                            List fileList = null;
                            try {
                                fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                                if (fileList.size() > 0) {
                                    table.clearSelection();
                                    Point point = dtde.getLocation();
                                    int row = table.rowAtPoint(point);
                                    DefaultTableModel model = (DefaultTableModel) table.getModel();
                                    for (Object value : fileList) {
                                        if (value instanceof File) {
                                            File f = (File) value;
                                            if (row < 0) {
                                                model.addRow(new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});
                                            } else {
                                                model.insertRow(row, new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});
                                                row++;
                                            }
                                        }
                                    }
                                }
                            } catch (UnsupportedFlavorException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        } else {
                            dtde.rejectDrop();
                        }
                    }
    
                });
    
                add(scroll, BorderLayout.CENTER);
            }
        }
    }
    

    0 讨论(0)
提交回复
热议问题