java - JTable + DnD : why is first hovered row after drag row selected? -


i've got jtable supports reordering dragging , dropping rows. works well. however, every time drag initiated on given row first subsequent row mouse hovers on gets selected.

even though sounds weird, not happen if click on row (to initiate drag) , move mouse right or left (as opposed or down). in case (when moving mouse right or left) row on drag initiated remains selected.

this behaviour applies both java (metal) l&f linux (gtk+) l&f.

it should of interest, i've provided sscce.

package com.tracker.workspace.ui.views.test;  import java.awt.borderlayout; import java.awt.dimension; import java.awt.datatransfer.dataflavor; import java.awt.datatransfer.transferable; import java.awt.datatransfer.unsupportedflavorexception; import java.awt.dnd.dndconstants; import java.awt.dnd.draggestureevent; import java.awt.dnd.draggesturelistener; import java.awt.dnd.dragsource; import java.io.ioexception; import java.io.serializable; import java.util.uuid; import javax.swing.dropmode; import javax.swing.jframe; import javax.swing.jtable; import javax.swing.listselectionmodel; import javax.swing.transferhandler; import javax.swing.transferhandler.transfersupport; import javax.swing.table.defaulttablemodel;  public class main {      private final jtable table;      public main() {          table = new jtable();         table.setmodel(new defaulttablemodel() {              @override             public int getrowcount() {                 return 5;             }              @override             public int getcolumncount() {                 return 5;             }              @override             public object getvalueat(int r, int c) {                 return r * c;             }         });          // set drag , drop on table.         dragsource.getdefaultdragsource().createdefaultdraggesturerecognizer(table, dndconstants.action_move, new defaultdragtoreordertablegesturelistener(table));         table.setselectionmode(listselectionmodel.single_selection);         table.setdragenabled(true);         table.setdropmode(dropmode.insert_rows);         table.settransferhandler(new defaultdragtoreordertabletransferhandler(table) {              public boolean moverow(int source, int target) {                 return true;             }         });          // set frame.         jframe frame = new jframe("mainframe");         frame.setsize(new dimension(640, 480));         frame.getcontentpane().add(table, borderlayout.center);         frame.pack();         frame.setvisible(true);      }      public class defaultdragtoreordertablegesturelistener implements draggesturelistener {          private final jtable table;         private final int[] alloweddragcolumns;          public defaultdragtoreordertablegesturelistener(jtable table) {             this.table = table;             this.alloweddragcolumns = new int[0];         }          public defaultdragtoreordertablegesturelistener(jtable table, int[] alloweddragcolumns) {             this.table = table;             this.alloweddragcolumns = alloweddragcolumns;         }          public void draggesturerecognized(draggestureevent e) {              boolean candrag = false;              //we allow people drag specific columns.             if (alloweddragcolumns.length > 0) {                 (int = 0; < alloweddragcolumns.length; i++) {                     if (table.convertcolumnindextomodel(table.columnatpoint(e.getdragorigin())) == alloweddragcolumns[i]) {                         candrag = true;                     }                 }              } else {                 candrag = true;             }              if (!candrag) {                 return;             }              // source row.             //int sourcerow = table.convertrowindextomodel(table.getselectedrow());             int sourcerow = table.rowatpoint(e.getdragorigin().getlocation());             sourcerow = table.convertrowindextomodel(sourcerow);              //we permit user drag rows within same table,             //and not other components. thus, not need create             //transfer object hold kind of data.             e.startdrag(null, new integertransferobject(sourcerow));         }     }      public abstract class defaultdragtoreordertabletransferhandler extends transferhandler {          private final jtable table;         private final int[] alloweddropcolumns;          public defaultdragtoreordertabletransferhandler(jtable table) {             this.table = table;             this.alloweddropcolumns = new int[0];         }          public defaultdragtoreordertabletransferhandler(jtable table, int[] alloweddropcolumns) {             this.table = table;             this.alloweddropcolumns = alloweddropcolumns;         }          @override         public boolean canimport(transfersupport support) {              //do not allow user perform action not drop action.             if (!support.isdrop()) {                 return false;             }              //do not allow user perform action involves data             //flavor other empty flavor.             if (!support.gettransferable().isdataflavorsupported(new dataflavor(integer.class, "integertransferobject"))) {                 return false;             }              //we allow people drag specific columns.             boolean candrop = false;             if (alloweddropcolumns.length > 0) {                 (int = 0; < alloweddropcolumns.length; i++) {                     if (table.convertcolumnindextomodel(table.columnatpoint(support.getdroplocation().getdroppoint())) == alloweddropcolumns[i]) {                         candrop = true;                     }                 }              } else {                 candrop = true;             }              if (!candrop) {                 return false;             }              //do not allow user drop action involving data other components.             if (support.getcomponent() != table) {                 return false;             }              // not allow drops above source row or below source row.             try {                  // source row.                 integer sourcerow = (integer) support.gettransferable().gettransferdata(new dataflavor(integer.class, "integertransferobject"));                  // target row.                 int targetrow = table.rowatpoint(support.getdroplocation().getdroppoint());                 targetrow = table.convertrowindextomodel(targetrow);                  // validate drop row not adjacent drag row.                 if (targetrow == sourcerow || sourcerow + 1 == targetrow || sourcerow - 1 == targetrow) {                     return false;                 }              } catch (exception e) {                 return false;             }              return true;          }          @override         public boolean importdata(transfersupport support) {              //validate drop action.             if (!canimport(support)) {                 return false;             }              try {                  //get source row.                 integer sourcerow = (integer) support.gettransferable().gettransferdata(new dataflavor(integer.class, "integertransferobject"));                  //get target row.                 int targetrow = table.rowatpoint(support.getdroplocation().getdroppoint());                 targetrow = table.convertrowindextomodel(targetrow);                  //reorder rows based on user's gestures.                 return moverow(sourcerow, targetrow);              } catch (exception e) {                 return false;             }         }          /**          * returns table handler operates on.          *          * @return  <code>jtable</code> handler operates on.          */         protected jtable gettable() {             return table;         }          /**          * moves row @ source position target position. method          * returns <b>false</b> default, , expected overridden.          *          * @param   source <code>int</code> being row moved.          * @param   target <code>int</code> being row's target position.          * @return  <code>boolean</code> indicating wether move carried          *          out successfully.          */         public abstract boolean moverow(int source, int target);     }      public class anonymoussource implements transferobjectsource {          public uuid getsourceid() {             return null;         }     }      public class integertransferobject extends transferobject {          private final int integer;         private final transferobjectsource source;          public integertransferobject(int integer) {             this.integer = integer;             this.source = new anonymoussource();         }          public integertransferobject(int integer, transferobjectsource source) {             this.integer = integer;             this.source = source;         }          public int getinteger() {             return integer;         }          public dataflavor[] gettransferdataflavors() {             return new dataflavor[]{new dataflavor(integer.class, "integertransferobject")};         }          public boolean isdataflavorsupported(dataflavor dataflavor) {             dataflavor[] dataflavors = gettransferdataflavors();             (int = 0; < dataflavors.length; i++) {                 if (dataflavors[i].equals(dataflavor)) {                     return true;                 }             }             return false;         }          public object gettransferdata(dataflavor dataflavor) throws unsupportedflavorexception, ioexception {             if (isdataflavorsupported(dataflavor)) {                 return integer;             } else {                 throw new unsupportedflavorexception(dataflavor);             }         }          @override         public transferobjectsource getsource() {             return source;         }     }      public abstract class transferobject implements transferable, serializable {          public abstract transferobjectsource getsource();      }          public interface transferobjectsource {          public uuid getsourceid();      }          public static void main(string[] args) {         main m = new main();     } } 


Comments