Java核心技术II-第6章-对象查看树-源代码
Java核心技术II-第6章-对象查看树-源代码,在博文的最后有运行效果图。
package javaee.vii.ch06;
import java.awt.EventQueue;
import javax.swing.JFrame;
/**
* This program demonstrates how to use a custom tree model. It displays the fields of an object.
* @author lcwell
*/
public class ObjectInspectorTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
@Override
public void run() {
JFrame frame = new ObjectInspectorFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
package javaee.vii.ch06;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
/**
* This frame holds the object tree.
* @author lcwell
*/
public class ObjectInspectorFrame extends JFrame {
public ObjectInspectorFrame() {
setTitle("ObjectInspectorTest");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// we inspect this frame object
Variable v = new Variable(getClass(), "this", this);
ObjectTreeModel model = new ObjectTreeModel();
model.setRoot(v);
// construct and show tree
tree = new JTree(model);
add(new JScrollPane(tree), BorderLayout.CENTER);
}
private JTree tree;
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 300;
}
package javaee.vii.ch06;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.EventListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
/**
* This tree model describes the tree structure of a Java object. Children are the objects.
* @author lcwell
*/
public class ObjectTreeModel implements TreeModel{
public ObjectTreeModel() {
root = null;
}
/**
* Sets the root to a given variable.
* @param v the variable that is beging described this tree.
*/
public void setRoot(Variable v) {
Variable oldRoot = v;
root = v;
fireTreeStructureChanged(oldRoot);
}
@Override
public Object getRoot() {
return root;
}
@Override
public Object getChild(Object parent, int index) {
ArrayList<Field> fields = ((Variable) parent).getFields();
Field f = (Field) fields.get(index);
Object parentValue = ((Variable) parent).getValue();
try {
return new Variable(f.getType(), f.getName(), f.get(parentValue));
} catch (IllegalAccessException e) {
return null;
}
}
@Override
public int getChildCount(Object parent) {
return ((Variable) parent).getFields().size();
}
@Override
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
}
@Override
public int getIndexOfChild(Object parent, Object child) {
int n = getChildCount(parent);
for (int i = 0; i < n; i++) {
if (getChild(parent, i).equals(child)) return i;
}
return -1;
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
protected void fireTreeStructureChanged(Object oldRoot) {
TreeModelEvent event = new TreeModelEvent(this, new Object[]{oldRoot});
EventListener[] listeners = listenerList.getListeners(TreeModelListener.class);
for (int i = 0; i < listeners.length; i++) {
((TreeModelListener) listeners[i]).treeStructureChanged(event);
}
}
private Variable root;
private EventListenerList listenerList = new EventListenerList();
}
package javaee.vii.ch06;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
/**
* A variable with a type, name, and value.
* @author lcwell
*/
public class Variable {
/**
* Construct a variable
* @param aType the type
* @param aName the name
* @param aValue the value
*/
public Variable(Class<?> aType, String aName, Object aValue) {
type = aType;
name = aName;
value = aValue;
fields = new ArrayList<Field>();
// find all fields if we have a class type except we don't expand strings and null values
if (!type.isPrimitive() && !type.isArray() && !type.equals(String.class) && value != null) {
// get fields from the class and all superclasses
for (Class<?> c = value.getClass(); c != null; c = c.getSuperclass()) {
Field[] fs = c.getDeclaredFields();
AccessibleObject.setAccessible(fs, true);
// get all nonstatic fields
for (Field f : fs)
if ((f.getModifiers() & Modifier.STATIC) == 0) fields.add(f);
}
}
}
/**
* Get the value of this variable.
* @return an array list of varialbes describing the fields
*/
public Object getValue() {
return value;
}
/**
* Gets all nonstatic fields of this variable
* @return an array list of varialbes describing the fields
*/
public ArrayList<Field> getFields() {
return fields;
}
@Override
public String toString() {
String r = type + " " + name;
if (type.isPrimitive()) r += "=" + value;
else if (type.equals(String.class)) r += "=" + value;
else if (value == null) r += "=null";
return r;
}
private Class<?> type;
private String name;
private Object value;
private ArrayList<Field> fields;
}
运行效果: