/*
* Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.com/javaexamples2.
*/
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Arrays;
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* This class is a JTable subclass that displays a table of the JavaBeans
* properties of any specified class.
*/
public class PropertyTable extends JTable {
/** This main method allows the class to be demonstrated standalone */
public static void main(String[] args) {
// Specify the name of the class as a command-line argument
Class beanClass = null;
try {
// Use reflection to get the Class from the classname
beanClass = Class.forName("javax.swing.JLabel");
} catch (Exception e) { // Report errors
System.out.println("Can't find specified class: " + e.getMessage());
System.out.println("Usage: java TableDemo <JavaBean class name>");
System.exit(0);
}
// Create a table to display the properties of the specified class
JTable table = new PropertyTable(beanClass);
// Then put the table in a scrolling window, put the scrolling
// window into a frame, and pop it all up on to the screen
JScrollPane scrollpane = new JScrollPane(table);
JFrame frame = new JFrame("Properties of JavaBean: ");
frame.getContentPane().add(scrollpane);
frame.setSize(500, 400);
frame.setVisible(true);
}
/**
* This constructor method specifies what data the table will display (the
* table model) and uses the TableColumnModel to customize the way that the
* table displays it. The hard work is done by the TableModel implementation
* below.
*/
public PropertyTable(Class beanClass) {
// Set the data model for this table
try {
setModel(new JavaBeanPropertyTableModel(beanClass));
} catch (IntrospectionException e) {
System.err.println("WARNING: can't introspect: " + beanClass);
}
// Tweak the appearance of the table by manipulating its column model
TableColumnModel colmodel = getColumnModel();
// Set column widths
colmodel.getColumn(0).setPreferredWidth(125);
colmodel.getColumn(1).setPreferredWidth(200);
colmodel.getColumn(2).setPreferredWidth(75);
colmodel.getColumn(3).setPreferredWidth(50);
// Right justify the text in the first column
TableColumn namecol = colmodel.getColumn(0);
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(SwingConstants.RIGHT);
namecol.setCellRenderer(renderer);
}
/**
* This class implements TableModel and represents JavaBeans property data
* in a way that the JTable component can display. If you've got some type
* of tabular data to display, implement a TableModel class to describe that
* data, and the JTable component will be able to display it.
*/
static class JavaBeanPropertyTableModel extends AbstractTableModel {
PropertyDescriptor[] properties; // The properties to display
/**
* The constructor: use the JavaBeans introspector mechanism to get
* information about all the properties of a bean. Once we've got this
* information, the other methods will interpret it for JTable.
*/
public JavaBeanPropertyTableModel(Class beanClass)
throws java.beans.IntrospectionException {
// Use the introspector class to get "bean info" about the class.
BeanInfo beaninfo = Introspector.getBeanInfo(beanClass);
// Get the property descriptors from that BeanInfo class
properties = beaninfo.getPropertyDescriptors();
// Now do a case-insensitive sort by property name
// The anonymous Comparator implementation specifies how to
// sort PropertyDescriptor objects by name
Arrays.sort(properties, new Comparator() {
public int compare(Object p, Object q) {
PropertyDescriptor a = (PropertyDescriptor) p;
PropertyDescriptor b = (PropertyDescriptor) q;
return a.getName().compareToIgnoreCase(b.getName());
}
public boolean equals(Object o) {
return o == this;
}
});
}
// These are the names of the columns represented by this TableModel
static final String[] columnNames = new String[] { "Name", "Type",
"Access", "Bound" };
// These are the types of the columns represented by this TableModel
static final Class[] columnTypes = new Class[] { String.class,
Class.class, String.class, Boolean.class };
// These simple methods return basic information about the table
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return properties.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public Class getColumnClass(int column) {
return columnTypes[column];
}
/**
* This method returns the value that appears at the specified row and
* column of the table
*/
public Object getValueAt(int row, int column) {
PropertyDescriptor prop = properties[row];
switch (column) {
case 0:
return prop.getName();
case 1:
return prop.getPropertyType();
case 2:
return getAccessType(prop);
case 3:
return new Boolean(prop.isBound());
default:
return null;
}
}
// A helper method called from getValueAt() above
String getAccessType(PropertyDescriptor prop) {
java.lang.reflect.Method reader = prop.getReadMethod();
java.lang.reflect.Method writer = prop.getWriteMethod();
if ((reader != null) && (writer != null))
return "Read/Write";
else if (reader != null)
return "Read-Only";
else if (writer != null)
return "Write-Only";
else
return "No Access"; // should never happen
}
}
}
|