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
Post a Comment