1

I have an app that has a JTable of some data.. So I add the data and it appears well.. But when I try to edit a cell, I can edit it but when I click enter or tab to save the new content it reflects as it was earlier.. I don't know why that happens.. I searched online but with no hope.. :(

Here is the Table Model class :

public class TableModel extends AbstractTableModel {

String[] columnNames = { "Col1", "Col2", "Col3", "Col4", "Col5", "Col6" };

private List<Entry> db;
JTable table;

public TableModel(JTable table) {
    this.table = table;
}

public void addRow(Entry entry) {
    db.add(entry);
    fireTableRowsInserted(db.size() - 1, db.size() - 1);
    table.editCellAt(db.size() -1, 0);
}

@Override
public boolean isCellEditable(int row, int column) {
    return true;
}

public void setData(List<Entry> db) {
    this.db = db;
}

@Override
public String getColumnName(int column) {
    return columnNames[column];
}

@Override
public int getColumnCount() {
    return 6;
}

@Override
public int getRowCount() {
    return db.size();
}

@Override
public Object getValueAt(int row, int col) {
    Entry entry = db.get(row);

    try {
        switch (col) {
        case 0:
            return entry.getItem();
        case 1:
            return entry.getTransPayment();
        case 2:
            return entry.getEquipPayment();
        case 3:
            return entry.getGasPayment();
        case 4:
            return entry.getEquipSparePayment();
        case 5:
            return entry.getTransSparePayment();
        case 6:
            return entry.getTotal();
        }
    } catch (Exception e) {
        fireTableDataChanged();
    }


    return null;
}


}

The question is : Do I need to add any custom methods or code to do what I mentioned ?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Muhammad Ashraf
  • 1,252
  • 1
  • 14
  • 32

2 Answers2

2

I was hoping you could do this with a custom TableCellEditor, but that didn't turn out to be the case.

You need to provide a key binding for the Enter key, which would allow you to associate an appropriate action for the key, for example...

public class EditSelectedCellAction extends AbstractAction {

    private JTable table;

    public EditSelectedCellAction(JTable table) {
        this.table = table;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        int col = table.getSelectedColumn();
        int row = table.getSelectedRow();

        if (col >= 0 && row >= 0) {
            table.editCellAt(row, col);
        }
    }

}

You would then need to bind the EditSelectedCellAction to the Enter key, for example...

InputMap im = table.getInputMap(JTable.WHEN_FOCUSED);
ActionMap am = table.getActionMap();

KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
im.put(enterKey, "Action.enter");
am.put("Action.enter", new EditSelectedCellAction(table));

Feedback

There is never any reason why a model should ever have a reference to any view component, ever. The model should simply not care. A model could be associated with multiple views (in this case, tables), making in practical to maintain a reference to any view component.

Instead, what ever is calling your addRow method should be making the decisions to edit the cell. Maybe, your addRow method could return the row index.

Also, in you getValueAt method, you call fireTableDataChanged(); if, for some reason, something goes wrong, this could set up a nasty chain reaction which could place your program in an infinite loop and is best avoided

Updated

You know, at first, I though you hadn't overriden isCellEditable, but as it turns out, you've not override setValueAt

@Override
public void setValueAt(Object aValue, int rowIndex, int colIndex) {
    Entry entry = db.get(rowIndex);
    switch (colIndex) {
        case 0:
            entry.getItem();
            break;
        case 1:
            entry.setTransPayment(aValue);
            break;
        case 2:
            entry.setEquipPayment(aValue);
            break;
        case 3:
            entry.setGasPayment(aValue);
            break;
        case 4:
            entry.setEquipSparePayment(aValue);
            break;
        case 5:
            entry.setTransSparePayment(aValue);
            break;
        case 6:
            entry.setTotal(aValue);
            break;
    }
    fireTableCellUpdated(rowIndex, colIndex);
}

Now, because you didn't provide the source for Entry, I need to guess at its data types and functionality

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
2

but when I click enter or tab to save the new content it reflects as it was earlier..

Your TableModel doesn't implement the setValueAt(...) method so the data from the editor is never saved.

@Override
public void setValueAt(Object value, int row, int column)
{
    Entry entry = db.get(row);

    switch (column)
    {
        case 0: entry.setItem(value); break;
        case 1: entry.setTransPayment(value); break;
        ...
    }

    fireTableCellUpdated(row, column);
}
camickr
  • 321,443
  • 19
  • 166
  • 288