incubus
incubus

Reputation: 1009

JTable setting a default editor for a custom class

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

Answers (2)

incubus
incubus

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

trashgod
trashgod

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

Related Questions