问题
I have extended the AbstractTableModel class to make my JTable non-editable,expects the first row. By the way, i have overrided the isCellEditable(int row, int col) methode.By putting an integer variable, that hold the nextRow to activate, i got the first row respects my creterias.So, the problem is to make the next row active when the the cell in previous row column zero is filled by the user (data changed and must have a value).Her is my code so far.
package MODEL.tableModel;
import MODEL.Produit;
import MODEL.ProduitInBonDachat;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
public class BonDachatTableModel extends AbstractTableModel implements TableModelListener {
private String headerTitle[] = {"Designation", "Qté", "Prix Unitaire", "Sous Total"};
private List<ProduitInBonDachat> data;
// variable that hold the next
private int nextActiveRow = 0;
public BonDachatTableModel() {
data = new ArrayList<ProduitInBonDachat>();
}
@Override
public String getColumnName(int i) {
return headerTitle[i];
}
@Override
public int getRowCount() {
return 10;
}
@Override
public int getColumnCount() {
return headerTitle.length;
}
public void tableChanged(TableModelEvent event) {
int col = event.getColumn();
int fRow = event.getFirstRow();
if ((col == 1) && (col == 2)) {
setValueAt(getValueAt(fRow, col), fRow, col);
fireTableCellUpdated(fRow, col);
}
}
public Object getValueAt(int row, int col) {
try {
data.get(row);
} catch (IndexOutOfBoundsException e) {
return null;
}
ProduitInBonDachat pInBonDachat = data.get(row);
switch (col) {
case 0:
if (pInBonDachat.getDesignationProduit() == null) {
return null;
}
if(!pInBonDachat.getDesignationProduit().isEmpty()){
nextActiveRow++ ;
fireTableCellUpdated(row, col);
}
return pInBonDachat.getDesignationProduit();
case 1:
if (pInBonDachat.getQte() == null) {
return null;
}
return pInBonDachat.getQte();
case 2:
if (pInBonDachat.getPrixDeVente() == null) {
return null;
}
return pInBonDachat.getPrixDeVente();
case 3:
if (pInBonDachat.getPrixDeVente() == null || pInBonDachat.getQte() == null) {
return null;
}
return pInBonDachat.getQte().multiply(pInBonDachat.getPrixDeVente());
default:
return null;
}
}
public boolean isCellEditable(int row, int col) {
if(col == 1 || col == 2 || row == nextActiveRow)
return true;
else
return false ;
}
@Override
public void setValueAt(Object value, int row, int col) {
ProduitInBonDachat tableEtry;
try {
tableEtry = data.get(row);
} catch (IndexOutOfBoundsException e) {
tableEtry = new ProduitInBonDachat();
data.add(row, tableEtry);
}
switch (col) {
case 0:
tableEtry.setDesignationProduit((String) value);
nextRowActive();
fireTableCellUpdated(int row, int col);
break;
case 1:
tableEtry.setQte((BigDecimal) value);
break;
case 2:
tableEtry.setPrixDeVente((BigDecimal) value);
break;
default:
super.setValueAt(value, row, col);
}
}
@Override
public Class<?> getColumnClass(int col) {
switch (col) {
case 0:
return String.class;
case 1:
return BigDecimal.class;
case 2:
return BigDecimal.class;
case 3:
return BigDecimal.class;
default:
return super.getColumnClass(col);
}
}
public void nextRowActive(){
nextActiveRow++;
}
}
回答1:
Basically, your current method will return false
if the current column is not 0
, otherwise it will return true
Maybe something like...
public boolean isCellEditable(int row, int col) {
boolean isEditable = false;
System.out.println("update cell edittable");
if(col != 0 && row == nextActiveRow){
isEditable = true;
}
return isEditable;
}
Will do a better job...
To update the nextActiveRow
value, you need to verify the validity of the current row and update it the variable when it's appropriate, for example...
public void setValueAt(Object value, int row, int col) {
ProduitInBonDachat tableEtry;
try {
tableEtry = data.get(row);
switch (col) {
case 0:
tableEtry.setDesignationProduit((String) value);
break;
case 1:
tableEtry.setQte((BigDecimal) value);
break;
case 2:
tableEtry.setPrixDeVente((BigDecimal) value);
break;
}
fireTableCellUpdated(row, col);
if (row == nextActiveRow && activeRowIsVaid()) {
nextRowActive();
}
} catch (IndexOutOfBoundsException e) {
// IMHO, this is not an appropriate action for the
// setValueAt method, as the contract suggest that you are
// editing an existing row, instead provide a method in your model
// which is responsible for inserting/adding new rows
//tableEtry = new ProduitInBonDachat();
//data.add(row, tableEtry);
// don't forget to fireRowInserted!
}
}
回答2:
Here is solution that work for me, a JTable that is activated row by row , when the first column is filled up.
package MODEL.tableModel;
import MODEL.Produit;
import MODEL.ProduitInBonDachat;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
public class BonDachatTableModel extends AbstractTableModel implements TableModelListener {
private String headerTitle[] = {"Designation", "Qté", "Prix Unitaire", "Sous Total"};
private List<ProduitInBonDachat> data;
private int nextActiveRow = 0;
public BonDachatTableModel() {
data = new ArrayList<ProduitInBonDachat>();
}
@Override
public String getColumnName(int i) {
return headerTitle[i];
}
@Override
public int getRowCount() {
return 10;
}
@Override
public int getColumnCount() {
return headerTitle.length;
}
public void tableChanged(TableModelEvent event) {
int col = event.getColumn();
int fRow = event.getFirstRow();
if ((col == 1) && (col == 2)) {
setValueAt(getValueAt(fRow, col), fRow, col);
fireTableCellUpdated(fRow, col);
}
}
public Object getValueAt(int row, int col) {
try {
data.get(row);
} catch (IndexOutOfBoundsException e) {
return null;
}
ProduitInBonDachat pInBonDachat = data.get(row);
switch (col) {
case 0:
if (pInBonDachat.getDesignationProduit() == null) {
return null;
}
return pInBonDachat.getDesignationProduit();
case 1:
if (pInBonDachat.getQte() == null) {
return null;
}
return pInBonDachat.getQte();
case 2:
if (pInBonDachat.getPrixDeVente() == null) {
return null;
}
return pInBonDachat.getPrixDeVente();
case 3:
if (pInBonDachat.getPrixDeVente() == null || pInBonDachat.getQte() == null) {
return null;
}
return pInBonDachat.getQte().multiply(pInBonDachat.getPrixDeVente());
default:
return null;
}
}
public boolean isCellEditable(int row, int col) {
if (col == 0 && row <= nextActiveRow) {
return true;
}
if (col == 1 && row <= nextActiveRow) {
return true;
}
if (col == 2 && row <= nextActiveRow) {
return true;
}
return false;
}
@Override
public void setValueAt(Object value, int row, int col) {
ProduitInBonDachat tableEtry;
try {
tableEtry = data.get(row);
} catch (IndexOutOfBoundsException e) {
tableEtry = new ProduitInBonDachat();
data.add(row, tableEtry);
}
switch (col) {
case 0:
String valueCast = (String) value;
if (valueCast.isEmpty()) {
break;
}
nextActiveRow++;
tableEtry.setDesignationProduit((String) value);
break;
case 1:
tableEtry.setQte((BigDecimal) value);
break;
case 2:
tableEtry.setPrixDeVente((BigDecimal) value);
break;
default:
super.setValueAt(value, row, col);
}
fireTableCellUpdated(row, col);
}
@Override
public Class<?> getColumnClass(int col) {
switch (col) {
case 0:
return String.class;
case 1:
return BigDecimal.class;
case 2:
return BigDecimal.class;
case 3:
return BigDecimal.class;
default:
return super.getColumnClass(col);
}
}
public void nextRowActive() {
nextActiveRow++;
}
}
来源:https://stackoverflow.com/questions/27758904/dynamically-set-non-editable-jtable-row-as-editable