Reputation: 1009
I am having an issue with trying to set a default JTable cell editor for a custom class. I have several custom columns (numbers, strings and booleans). For the number types I use a my own cell editors and for the boolean and string types I just wanted to use the default ones provided by the JTable class.
I have the following code in the setup of my table:
JTable table;
....
table.setDefaultEditor(MyBoolean.class, table.getDefaultEditor(Boolean.class));
table.setDefaultRenderer(MyBoolean.class, table.getDefaultRenderer(Boolean.class));
table.setDefaultEditor(MyString.class, table.getDefaultEditor(String.class);
table.setDefaultRenderer(MyString.class, table.getDefaultRenderer(String.class);
The boolean type works as expected and I can click on the tickbox and have it turn on and off. The string type displays but will not let me edit. In my model I have it so that all columns return true for editable.
If I add the following to my model:
@Override
public Class<?> getColumnClass(int columnIndex){
Class<?> clz = columns.get(columnIndex).getClass();
if(clz.isAssignableFrom(MyString.class)){
return String.class;
}
return clz;
}
I can now edit the strings as expected.
My question: Why does setting the default editor not work for the string class but does for the boolean class? Why do I have to have a special case in the getColumnClass method in the model?
Upvotes: 1
Views: 2212
Reputation: 1009
I figured out why it was behaving the way I described originally. It finally clicked when I looked at the setValueAt
method:
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
rows.get(rowIndex).getValues().set(columnIndex, aValue);
fireTableCellUpdated(rowIndex, columnIndex);
}
and noticed that Object
was an instance of MyString
and the result in the cell came from Object.toString()
.
The reason MyString
came through to the method is because the GenericEditor
in JTable
(which covers the String
class) has the method getTableCellEditorComponent
which creates a java.lang.reflect.Constructor
object that is used to instantiate new instances of the objects allowed in this column. MyString
column class had a constructor that took a String
and hence it returned a new MyString
column instance to the setValueAt
method. When I changed the code in getColumnClass
(as shown above) to return String.class
, a new instance of String
was created when the editing stopped and it was passed to the setValueAt
method and hence correctly displaced in the cell.
Definitely learned a lot about JTables with this problem.
Upvotes: 1
Reputation: 205875
Assuming that you are extending DefaultTableModel
, note that getColumnClass()
, inherited from AbstractTableModel
, "returns Object.class
regardless of columnIndex
." As noted here, Object
"is rendered by a label that displays the object's string value." There is no default editor for Object
. In particular, "To specify more precise column types, the table model must define the getColumnClass()
method appropriately."
Upvotes: 1