ListTransferHandler in DropDemo has a bug
this is a repost from the OTN Discussions Forum because I did not get an answer there.
In Java, I would like to enable Drag and Drop in a JList containing Strings. To do that, I used the ListTransferHandler.java that is used in Oracle's DropDemo. Unfortunately, this ListTransferHandler.java has a bug.
To reproduce the error in the ListTransferHandler.java I did the following:
- download the Drop Demo Project fro开发者_如何学编程m http://download.oracle.com/javase/tutorial/uiswing/examples/zipfiles/dnd-DropDemoProject.zip
- run it in Netbeans
- change the List Drop Mode to INSERT
- drag and drop List Item 1 to above List Item 0
Instead of this:
- List Item 1
- List Item 0
I get this:
- List Item 1
- List Item 1
which is obviously not the expected result.
Netbeans' output window did not show any error messages. I tried to find the bug myself, but was not successful.
So am I missing the point of enabling DnD in a JList? Don't I need to implement a ListTransferHandler myself?
Has anybody a working ListTransferHandler for me please or know how to fix the one used in the demo?
Thanks and best regards, Kurt
That is definitely a bug. Take a look at the ListTransferHandler#cleanup method. Its goal is to delete previously selected item from the list. Indexes correction is performed before deletion:
if (addCount > 0) {
for (int i = 0; i < indices.length; i++) {
if (indices[i] > addIndex) {
indices[i] += addCount;
}
}
}
Somehow, method ListTransferHandler#importString that initializes addCount is never called, hence, correction is never done.
As a workaround, you can initialize it yourself:
int addCount = indices.length;
That will fix INSERT drop mode.
UPD:
Just noticed that other drop modes are broken too. So, the final fix (seems to be it):
public class ListTransferHandler extends TransferHandler {
private boolean insert;
//........
public boolean importData(TransferHandler.TransferSupport info) {
//......
insert = dl.isInsert();
//......
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, insert && action == TransferHandler.MOVE);
}
protected void cleanup(JComponent c, boolean remove) {
if (remove && indices != null) {
int addCount = indices.length;
//.....
}
Also, all unused fields and methods should be removed.
@n0weak thanks to your answer I could fix the ListTransferHandler for my needs (multiple selections are still broken, and I haven't tested other modes than INSERT).
I found it necessary to remember the addIndex
in addition to your solution above. Here are the code changes I used:
public class ListTransferHandler extends TransferHandler {
// ...
private boolean insert;
// ...
public boolean importData(TransferHandler.TransferSupport info) {
// ...
// method local variables were mistakenly used
insert = dl.isInsert();
addIndex = dl.getIndex(); // also replace index with addIndex a few lines below
addCount = indices.length;
// ...
protected void exportDone(JComponent c, Transferable data, int action) {
cleanup(c, insert && action == TransferHandler.MOVE);
}
/* protected void importString(JComponent c, String str) {...}
This method is never called */
精彩评论