开发者

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 */
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜