Search code examples
javaswinginterfacejtabletablemodel

Java TableModel implementation crashes the program


In my program I wish to show some data in a JTable. I have a class containing the data, so the easiest way to present it in a JTable seems to extend my class so that it implements TableModel interface and use it as a model for JTable. Unfortunately it does not work correctly for me. When the program is about to draw the JTable, a NullPointerException is thrown at javax.swing.JTable.prepareRenderer(). Why?

package bridgecalc;

import java.util.HashSet;

import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class MyTableModel extends MyDataClass implements TableModel {

    private static final long serialVersionUID = 1L;
    // private Object[][] data; //this is in fact declared in the superclass
    private static final String[] colNames = {"bla", "blabla", "hola", "hej", "egle", "begle", "eciepecie"};
    private HashSet<TableModelListener> listeners;

    public MyTableModel() {
        data = new Object[7][7];
        listeners = new HashSet<TableModelListener>();
    }

    @Override
    public int getColumnCount() {
        return data.length;
    }

    @Override
    public int getRowCount() {
        return data[0].length;
    }

    @Override
    public Object getValueAt(int arg0, int arg1) {
        return data[arg0][arg1];
    }

    @Override
    public void addTableModelListener(TableModelListener l) {
        listeners.add(l);
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return null;
    }

    @Override
    public String getColumnName(int columnIndex) {
        return colNames[columnIndex];
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (rowIndex == columnIndex)
            return false;
        else return true;
    }

    @Override
    public void removeTableModelListener(TableModelListener l) {        
        listeners.remove(l);
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        data[columnIndex][rowIndex] = aValue;
    }

}

And somewhere in the program:

...
JTable table = new JTable(new MyTableModel());
this.setViewportView(table);
...

Thanks in advance for any help.


Solution

  • Perhaps your problem was the getColumnClass() returning null instead of Object.class

    Use AbstractTableModel as your base class. This way you won't need so many methods. As it is you have just started to handle all the event stuff needed. If you want to do it, copy that code from 'AbstractTableModel` using either the Oracle/Sun source or some other source. Here is some source for some version that will give you and idea of how much code there is to handle the events: Java Source for AbstractTableModel

    public class MyTableModel extends AbstractTableModle {
    
    private MyDataClass myData; // holds the cell data
    
    private static final String[] colNames = {"bla", "blabla", "hola", "hej", "egle", "begle", "eciepecie"};
    
    public MyTableModel(MyDataClass val) {
        myData = val;
        myData.data = new Object[7][7];
    }
    
    @Override
    public int getColumnCount() {
        return myData.data.length;
    }
    
    @Override
    public int getRowCount() {
        return myData.data[0].length;
    }
    
    @Override
    public Object getValueAt(int arg0, int arg1) {
        return myData.data[arg0][arg1];
    }
    
    @Override
    public String getColumnName(int columnIndex) {
        return colNames[columnIndex];
    }
    
    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        if (rowIndex == columnIndex)
            return false;
        else return true;
    }
    
    @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            myData.data[columnIndex][rowIndex] = aValue;
        }
    
    }