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);
}
}
}