Table model

Overview Basic version Model Cell Renderer Editor Column widths Tooltips Controls in cells

Suppose we want the table data to hold more than one type, to allow the user to edit some but not all cells, and that we are able to have the data modified and the table display updated as a result. We cannot do that with the default model - instead we need to use an instance of our own model class.

We can define the model class by sub-classing AbstractTableModel. The actual data is an instance variable of the class. You need to define methods to return the number of columns, rows, which cells are editable and so on - all simple and logical.

For example, we will produce this:

The end column is boolean data, not String. We will allow the user to edit that, but nothing else. And if other code alters the data, the table will be updated to show it.

Our table model class is:

class MyModel extends AbstractTableModel {
    private String[] columnNames = {"Country", "Capital", "EU member?"};
    private Object[][] data = {
        {"UK", "London"},
        {"France", "Paris"},
        {"Spain", "Madrid"},
        {"Italy", "Rome"},
        {"Switzerland", "Geneva"}
    private Boolean[] endCol = {true, true, true, true, false};

    public int getColumnCount() {
        return columnNames.length;

    public int getRowCount() {
        return data.length;

    public String getColumnName(int col) {
        return columnNames[col];

    public Object getValueAt(int row, int col) {
        if (col == 2) {
            return endCol[row];
        return data[row][col];

    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();

    public boolean isCellEditable(int row, int col) {
        if (col == 2) {
            return true;
        } else {
            return false;


    public void setValueAt(Object value, int row, int col) {
        if (col == 2) {
            endCol[row] = (Boolean) value;
        } else {
            data[row][col] = value;
        fireTableCellUpdated(row, col);

And we create the table by:

        MyModel data = new MyModel();
        table = new JTable(data); 


We can show how the table will reflect changes to the underlying model, by creating the table, having a delay then changing the data, like this:

            final TestDlg dlg = new TestDlg(this, "Model", false);
            // action to be done when timer triggers
            ActionListener al = new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dlg.table.getModel().setValueAt(true, 4, 2);
            // create timer 
            Timer timer = new Timer(0, al);
            // will trigger after 3 seconds
            timer.setRepeats(false); // no repeat