while dragging column 3 (selected cell is edited) before column 2 after the operation is complete, value of col 3 is displayed in both new col 2 and former col 3 (should contain value of former col 2)
example, if the content of columns is a b c
Before dragging:
table: a b c
model: a b c
After dragging:
table: a c c
model: a c c
tracking invocation of [model]setValueAt(...) during the drag and drop, I realize the method is called with col 3 as argument, passing "c" as object, so the col 3 of model is re-setted to "c", ok, then it is called with col 2 as argument (which should not), passing "c" as object. My question is why and by what setValueAt is called with 2 as column, when 2 is the column in view, not in model. I do not invoque the method in my code.
Even when commenting putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); the setValueAt is still invocated.
Note : I am doing a few hacks with focus in my jtable, and use a personnal editor. the table :
public PersoTable(final PgTable pgt, PersoTableModel persotablemodel) {
super(persotablemodel);
/*
* parcours des colonnes utiles (action et inforow comptent pas)
*/
sorter = new TableRowSorter<>(this.getModel());
this.setRowSorter(sorter);
for (int i = 0; i < pgt.getNbCols(); i++) {
sorter.setComparator(i, new PersoTriable());
}
DocumentListener dl = new DocumentListener() {
/*
* on créé ici car un seul suffit pour la tableFiltre.
* Dans l'Editot il serait instancié plusieurs fois
*/
@Override
public void insertUpdate(DocumentEvent e) {
filtre(pgt);
}
@Override
public void removeUpdate(DocumentEvent e) {
filtre(pgt);
}
@Override
public void changedUpdate(DocumentEvent e) {
filtre(pgt);
}
};
ge = new PersoEditor(pgt, dl);
gr = new PersoRender(pgt);
setDefaultRenderer(String.class, gr);
setDefaultEditor(String.class, ge);
removeColumn(getColumnModel().getColumn(INFO_ROW_COL));
setShowGrid(false);
setIntercellSpacing(new Dimension(0, 0));
setFillsViewportHeight(true);
/**
* pour mise en édit qd on vient sur la jtable par une tabulation
*/
addFocusListener(new GfocusAdapter());
getTableHeader().addMouseListener(PersoTableTriEcouteur.getInstance());
/*
* mouseMotion car besoin du move
*/
addMouseMotionListener(PersoMouseAdapter.getInstance());
addMouseListener(PersoMouseAdapter.getInstance());
putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
}
the model
public class PersoTableModel extends AbstractTableModel {
boolean DEBUG = true;
private String[] entetes;
private List<ParDesc> listePardesc;
public PersoTableModel(List<ParDesc> data, PgTable pgtable) {
// dans pgt on a déclaré x colonnes.
// mais columnNames contient en plus :
// - la 1ere colonne contenant les InfoRow.
// - la colonne action
entetes = new String[pgtable.getNbCols() + 2];// 2 premieres colonnes sans entetes
entetes[0] = "InfoRow";
entetes[1] = "";
for (int i = 0; i < pgtable.getNbCols(); i++) {
entetes[i + 2] = pgtable.getColName(i);
}
this.listePardesc = data;
}
public PersoTableModel(List<ParDesc> data, PgTable pgtable) {
this(data, pgtable);
}
public void addParDesc(int row, ParDesc parDesc) {
listePardesc.add(row, parDesc);
fireTableRowsInserted(row, listePardesc.size() - 1);
}
public void addParDesc(ParDesc parDesc) {
listePardesc.add(parDesc);
fireTableRowsInserted(listePardesc.size() - 1, listePardesc.size() - 1);
}
@Override
public int getColumnCount() {
return entetes.length;
}
@Override
public int getRowCount() {
return listePardesc.size();
}
@Override
public String getColumnName(int col) {
return entetes[col];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return listePardesc.get(rowIndex).getInfoRow();
case 1:
return listePardesc.get(rowIndex).getAction();
case 2:
return listePardesc.get(rowIndex).getRang();
case 3:
return listePardesc.get(rowIndex).getFld_key();
case 4:
return listePardesc.get(rowIndex).getLib();
case 5:
return listePardesc.get(rowIndex).getDebut();
case 6:
return listePardesc.get(rowIndex).getLg();
case 7:
return listePardesc.get(rowIndex).getDt_cre_maj();
default:
return null; //Ne devrait jamais arriver
}
}
public InfoRow getInfoRow(int row) {
return listePardesc.get(row).getInfoRow();
}
@Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return InfoRow.class;
default:
return String.class;
}
}
@Override
public boolean isCellEditable(int row, int col) {
//Note that the data/cell address is constant,
//no matter where the cell appears onscreen.
if (col == 7) {
return false;
} else {
return true;
}
}
@Override
public void setValueAt(Object value, int row, int col) {
if (value == null) {
return;
}
ParDesc pardesc = listePardesc.get(row);
if (DEBUG) {
System.out.println("On sette " + row + "," + col
+ " à " + value
+ " (instance de "
+ value.getClass() + ")");
}
String newVal = "";
if (value instanceof String) {
newVal = ((String) value).trim();
}
switch (col) {
case 0:
pardesc.setInfoRow((InfoRow) value);
break;
case 1:
pardesc.setAction(newVal);
break;
case 2:
pardesc.setRang(newVal);
break;
case 3:
pardesc.setFld_key(newVal);
break;
case 4:
pardesc.setLib(newVal);
break;
case 5:
pardesc.setDebut(newVal);
break;
case 6:
pardesc.setLg(newVal);
break;
case 7:
pardesc.setDt_cre_maj(newVal);
break;
}
fireTableCellUpdated(row, col);
if (DEBUG) {
printDebugData();
}
}
private void printDebugData() {
int numRows = getRowCount();
int numCols = getColumnCount();
System.out.print("Après set,");
for (int i = 0; i < numRows; i++) {
System.out.print(" row " + i + " =");
for (int j = 0; j < numCols; j++) {
String toto;
if (getValueAt(i, j) instanceof InfoRow) {
toto = ((InfoRow) getValueAt(i, j)).toString();
} else {
toto = (String) getValueAt(i, j);
}
if (toto.trim().isEmpty()) {
toto = "_";
}
toto+=" |";
System.out.print(" " + j + " " + toto);
}
System.out.println();
}
}
}