It makes it easy to create a table and sets up the default CellEditors automatically and can get and set data from the cell in the GUI to the Java object.
BeanTableModel:
package se.lesc.beantablemodel;
import java.beans.*;
import java.util.*;
import javax.swing.table.AbstractTableModel;
/**
* A table model where each row represents one instance of a Java bean.
* When the user edits a cell the model is updated.
*
* @author Lennart Schedin
*
* @param <M> The type of model
*/
@SuppressWarnings("serial")
public class BeanTableModel<M> extends AbstractTableModel {
private List<M> rows = new ArrayList<M>();
private List<BeanColumn> columns = new ArrayList<BeanColumn>();
private Class<?> beanClass;
public BeanTableModel(Class<?> beanClass) {
this.beanClass = beanClass;
}
public void addColumn(String columnGUIName, String beanAttribute,
EditMode editable) {
try {
PropertyDescriptor descriptor = new PropertyDescriptor(beanAttribute,
beanClass);
columns.add(new BeanColumn(columnGUIName, editable, descriptor));
} catch (Exception e) {
e.printStackTrace();
}
}
public void addColumn(String columnGUIName, String beanAttribute) {
addColumn(columnGUIName, beanAttribute, EditMode.NON_EDITABLE);
}
public void addRow(M row) {
rows.add(row);
}
public void addRows(List<M> rows) {
for (M row : rows) {
addRow(row);
}
}
public int getColumnCount() {
return columns.size();
}
public int getRowCount() {
return rows.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
BeanColumn column = columns.get(columnIndex);
M row = rows.get(rowIndex);
Object result = null;
try {
result = column.descriptor.getReadMethod().invoke(row);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
M row = rows.get(rowIndex);
BeanColumn column = columns.get(columnIndex);
try {
column.descriptor.getWriteMethod().invoke(row, value);
} catch (Exception e) {
e.printStackTrace();
}
}
public Class<?> getColumnClass(int columnIndex) {
BeanColumn column = columns.get(columnIndex);
Class<?> returnType = column.descriptor.getReadMethod().getReturnType();
return returnType;
}
public String getColumnName(int column) {
return columns.get(column).columnGUIName;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columns.get(columnIndex).editable == EditMode.EDITABLE;
}
public List<M> getRows() {
return rows;
}
public enum EditMode {
NON_EDITABLE,
EDITABLE;
}
/** One column in the table */
private static class BeanColumn {
private String columnGUIName;
private EditMode editable;
private PropertyDescriptor descriptor;
public BeanColumn(String columnGUIName, EditMode editable,
PropertyDescriptor descriptor) {
this.columnGUIName = columnGUIName;
this.editable = editable;
this.descriptor = descriptor;
}
}
}
A test class:
package se.lesc.beantablemodel;
import javax.swing.*;
import se.lesc.beantablemodel.BeanTableModel.EditMode;
@SuppressWarnings("serial")
public class TableTester extends JTable {
public TableTester() {
BeanTableModel<Person> model = new BeanTableModel<Person>(Person.class);
model.addColumn("Social Security Number", "socialSecurityNumber");
model.addColumn("Name", "name", EditMode.EDITABLE);
model.addColumn("Age", "age", EditMode.EDITABLE);
model.addColumn("Heigt (in cm)", "height", EditMode.EDITABLE);
model.addColumn("Has empoyment", "employed", EditMode.EDITABLE);
model.addRow(new Person("1", "David", 20, 170.5, true));
model.addRow(new Person("2", "Susan", 26, 162.0, false));
model.addRow(new Person("3", "Mark", 42, 180.5, false));
model.addRow(new Person("4", "Anna", 54, 168.0, true));
model.addRow(new Person("5", "Johan", 5, 120.5, false));
setModel(model);
}
public static class Person {
private String socialSecurityNumber;
private String name;
private Integer age;
private Double height;
private Boolean employed;
private String hiddenField;
public Person(String socialSecurityNumber, String name, Integer age,
Double height, Boolean isMale) {
this.socialSecurityNumber = socialSecurityNumber;
this.name = name;
this.age = age;
this.height = height;
this.employed = isMale;
}
public String getSocialSecurityNumber() {
return socialSecurityNumber;
}
public void setSocialSecurityNumber(String socialSecurityNumber) {
this.socialSecurityNumber = socialSecurityNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Boolean isEmployed() {
return employed;
}
public void setEmployed(Boolean employed) {
this.employed = employed;
}
public String getHiddenField() {
return hiddenField;
}
public void setHiddenField(String hiddenField) {
this.hiddenField = hiddenField;
}
}
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableTester table = new TableTester();
JScrollPane scollPane = new JScrollPane(table);
frame.setContentPane(scollPane);
frame.pack();
frame.setVisible(true);
}
}
Thanks, have you ever done a BeanTreeTableModel ?
ReplyDeleteThanks. BeanTableModel is very useful indeed...
ReplyDeleteThanks a lot. BeanTableModel is a very good tool.
ReplyDelete