/*
* Copyright (c) 2004 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd 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,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book,
* please visit http://www.davidflanagan.com/javaexamples3.
*/
package je3.gui;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*; // TableModel and other JTable-related classes
import java.beans.*; // For JavaBean introspection
import java.util.*; // For array sorting
/**
* 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(args[0]);
}
catch (Exception e) { // Report errors
System.out.println("Can't find specified class: "+e.getMessage());
System.out.println("Usage: java PropertyTable <bean 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: " + args[0]);
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
}
}
}
|