Bean Table Model
Posted by Rob Camick on November 27, 2008
The BeanTableModel is a concrete implementation of the RowTableModel introduced in a previous entry. It is used to display a bean in a row of a table. The model uses reflection to determine which properties of the bean should be displayed in the table.
The model will search the bean for all getter methods, (ie. method name starts with “get” or “is”) that require zero parameters to invoke the method. When a method described above is found, it will then check for a setter method (ie. method name starts with “set”) of the same name that requires a single parameter. This parameter must be of the same type returned by the getter method. These getter/setter methods will be used in the implementation the getValueAt() and setValueAt() methods of the model.
The method name will be used to create the column name for each method. Basically the prefix will be removed and a space will be inserted before each capital character of the method name. The return type of the getter methods will be used to set the column class of each column. Also, the default editability of the column can be set based on the presence of a setter method or not.
If we assume the existence of a simple bean, lets call it Person, with the following method signatures:
- String getFirstName()
- setFirstName(String firstName)
- String getLastName()
- setLastName(String lastName)
- int getAge()
…then the model would contain 3 columns:
- First Name – of class String and is editable
- Last Name – of class String and is editable
- Age – of class Integer and is not editable
You could manually set the First Name and Last Name columns to be non editable, but you cannot make the Age editable. To create a table using the Person bean your code would be:
BeanTableModel model = new BeanTableModel(Person.class);
JTable table = new JTable(model);
Unfortunately we need to use the Person.class as a parameter because reflection is used to find the getter/setter methods and Generics do not provide this information even though the appropriate type was used to create the class.
The above constructor allows us to find all the getter/setter methods defined in the specified class. However, many beans extend from a class other than Object, in which case you may want to see all the inherited properties in the model as well. In this case you will need to use the constructor that allows you to specify an ancestor class as well. Maybe something like this:
BeanTableModel model = new BeanTableModel(JButton.class, Component.class);
JTable table = new JTable(model);
Of course if you do execute the above code you will find that the table model contains 100 columns of data. Chances are you are not interested in all the columns, so you will have two choices:
- remove columns from the table view by using the TableColumnModel remove() method
- create a custom TableModel for the bean to only disply the columns you wish to see
I have included JButtonTableModel as a quick demo of how you might create such a custom model. The code is executable and contains code to create a table using the BeanTableModel or the JButtonTableModel so you can see the difference. Now the choice is up to you. In some situations you may want to use the BeanTableModel for its convenience. In other cases the small amount of work to create a custom model will pay off in the long run.
Note: as has been mentioned in the comments below the table column ordering cannot be controlled when using the BeanTableModel. Check out the new Table Column Reordering entry for a simple solution to reorder columns after the table has been created. The solution was based on the suggestion provided below. Thanks Andre.