Thursday, November 27, 2008

Table Model with Addnew row


Have you ever thought of having your JTable which show a add new row
like in the below screenshot ?



Well you only have to fool the JTable ;) and do some extra stuff in
your model. Below I will how to create the above table model.

In simple if we look at the JTable source we can see it uses
getRowCount
method when it draws table rows. That means
it will draw rows to match the number of rows in your model.
So the first thing you should do is to get a extra row painted
which really not in your model is to override the
getRowCount
method as below.

public final int getRowCount() {
if (dataList == null) {
return 0;
} else {
return dataList.size() + 1;
}
}

Note: dataList is the Collection what holding my data in the
model. If your extending the DefaultTableModel, then the
name dataList will be replace by dataVector variable name.

Ok now will the table will draw you a extra row ?
Nope. Because since the last row doesn't exist in my dataList
an ArrayIndexOutOfBoundsException will be thrown from the
model's getValueAt method. So next this is the method we
are going to override. What will do here is we have to take
care of the last row which is not in the dataList. To handle
that will define a method which will return default values for
each column so the TableCellRenderer can render that
value and TableCellEditor will use that value in edit mode.

public Object getColumnDefaultValue(int columnIndex) {
if (columnIndex == 0) {
return "";
} else {
return 0.0;
}
}

And the getValueAt method will be modified as below

public final Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == dataList.size()) {
return getColumnDefaultValue(columnIndex);
} else {
return super.getValueAt(rowIndex, columnIndex);
}
}

Ok now you will see your new row in the JTable. But still you
can't edit, because the setVaueAt method will fail since there
is nothing to edit in the dataList for this new row index.
So we have to override the setValueAt method as well.
What we have to do in this is if the new row index is
edited we have to create a new row in the dataList and
pass the call back the setValueAt in the super class. Here
is the code explaining how to do that.

public final void setValueAt(Object aValue,
int rowIndex, int columnIndex) {
if (rowIndex == dataList.size()) {
dataList.add(createNewTableRow());
}
super.setValueAt(aValue, rowIndex, columnIndex);
}


In the above code you can see I have used a method
createNewTableRow. This method take care of the new
row creation. You can find the code below.

public Object[] createNewTableRow() {
return new Object[]{"", 0.0};
}

Thats all, now you have a TableModel which shows
you new row at the end.