I wrote a custom table model. The goal of it is to bind values to a list. This list is used throughout the application. If a change is made in the table, anywhere else in the application that change is also reflected. My problem is, my table JTable does not display the rows.
This is my first custom table model, so I am not sure if I am missing something.
The table is created with this code:
public CBTable(List<T> elements, Class<T> classType) {
super(new BindingTableModel(elements));
this.tableModel = (BindingTableModel<T>) getModel();
this.classType = classType;
setBindings();
repaint();
}
An example of setBindings is this:
@Override
protected void setBindings() {
addBinding(ProfessionalDelegate.DELEGAGE_PROPERTY_TYPE,
"Type",
String.class,
false);
addBinding(ProfessionalDelegate.ENTITY_PROPERTY_NAME,
"Name",
String.class,
true);
...
And the actual model itself is this:
public class BindingTableModel<T> extends AbstractTableModel implements TableModel {
private List<T> elements;
private List<BindingTableModelInfo> bindingInfo;
private Map<Point, Object> valueMap;
public BindingTableModel(List<T> elements) {
this.elements = elements;
this.bindingInfo = new ArrayList<>();
valueMap = new HashMap<>();
bind();
for(int i = 0; i < getRowCount(); i++){
fireTableRowsInserted(i, i);
}
fireTableStructureChanged();
}
public void addBindingInfo(String propertyName, String columnName, Class colClass, boolean isEditable) {
bindingInfo.add(new BindingTableModelInfo(propertyName,
columnName,
colClass,
isEditable));
}
private void bind() {
for (int col = 0; col < getColumnCount(); col++) {
for (int row = 0; row < getRowCount(); row++) {
getValueAt(row, col);//this will init the map
}
}
}
public void addElement(T element){
elements.add(element);
}
public List<T> getElements(){
return elements;
}
public void removeElement(T element){
int index = elements.indexOf(element);
elements.remove(element);
fireTableRowsDeleted(index, index);
}
@Override
public int getRowCount() {
return elements.size();
}
@Override
public int getColumnCount() {
return bindingInfo.size();
}
@Override
public String getColumnName(int i) {
return bindingInfo.get(i).getColumnName();
}
@Override
public Class<?> getColumnClass(int i) {
return bindingInfo.get(i).getColumnClass();
}
@Override
public boolean isCellEditable(int row, int col) {
return bindingInfo.get(col).isIsEditable();
}
@Override
public Object getValueAt(int row, int col) {
Point point = new Point(row, col);
if (valueMap.containsKey(point)) {
return valueMap.get(point);
}
String property = bindingInfo.get(col).getProperty();
Class classType = bindingInfo.get(col).getColumnClass();
T element = elements.get(row);
Object retVal = Pojo.getValueByName(classType, element, property);
valueMap.put(point, retVal);
return retVal;
}
@Override
public void setValueAt(Object value, int row, int col) {
Point point = new Point(row, col);
if (valueMap.containsKey(point)) {
Object oldValue = valueMap.get(point);
if (oldValue != null && oldValue.equals(value)) {
return;
}
}
String property = bindingInfo.get(col).getProperty();
Class classType = bindingInfo.get(col).getColumnClass();
T element = elements.get(row);
Pojo.setValueByName(classType, element, property, value);
}
}
Be certain to fireTableCellUpdated()
or another appropriate event; this is typically done in your implementation of setValueAt()
:
@Override
public void setValueAt(Object value, int row, int col) {
…
fireTableCellUpdated(row, col);
}