2

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);
    }


}
user489041
  • 27,916
  • 55
  • 135
  • 204
  • Where do you `fireTable*Updated()`? – trashgod Mar 17 '15 at 20:59
  • Thats a good question, I dont. Where does that usually take place? – user489041 Mar 17 '15 at 20:59
  • @trashgod I have added fire events in the constructor of the model. No effect :( – user489041 Mar 17 '15 at 21:02
  • 1
    In your constructor you create a "tableModel" variable, but then you use a "dataModel" variable to set the model of the table. Seems wrong to me. You don't need the fireXXX events in the constructor, the table.setModel(...) will cause the table to be repainted. However, you do need to invoke fireXXX(...) statements in other methods that update the data in the TableModel, for example, the setValueAt(...) method. – camickr Mar 17 '15 at 21:03
  • @user489041: I've elaborated below. – trashgod Mar 17 '15 at 21:06

1 Answers1

4

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);
}

Complete examples are seen here and here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045