Ya hemos cambiado totalmente el aspecto de nuestro JTree. Vamos ahora a ver cosas sobre cómo editar los nodos.
El JTree por defecto no es editable, no podemos modificar el contenido de los nodos de un árbol desde el mismo JTree. Cambiar este comportamiento es fácil, basta llamar al método setEditable(true) del JTree para hacer que los nodos sean editables.
tree.setEditable(true);
Para editar un nodo, hay dos posibilidades según la API:
Sin embargo, el editor por defecto que pone el JTree tiene una pequeña pega. Convierte nuestro dato a String usando toString(), lo mete en un JTextField y recoge el valor editado del JTextField como String. Si editamos de la forma por defecto, nuestros datos se transformarán en String. Si metes un Integer en el "user object" del DefaultMutableTreeNode (ver ejemplo sencillo de JTree) y lo editas, se convetirá en un String, con un valor numérico dentro, pero String. Si el dato es una clase propia nuestra, que no conoce java, no te digo qué puede pasar y en qué queda convertido.
Vamos a ver en este tutorial cómo cambiar ese editor por defecto, de forma que podamos hacerlo como queramos y podamos editar cualquier tipo de dato que necesitemos, incluidos nuestras propias clases. Por supuesto, debermos hacer un editor específico para cada tipo de dato que queramos editar.
Veamos cómo es el proceso de edición. El JTree no tiene ni idea de cómo se edita un nodo, así que le pregunta a otra clase que tiene dentro sobre todo lo relacionado con este tema. Esta clase es el DefaultTreeCellEditor. En realidad le vale cualquier clase que implemente la interface TreeCellEditor, pero si no le pasamos una clase desde fuera que implemente esta interface, JTree usará el DefaultTreeCellEditor.
Cada vez que el usuario Federico Ratón hace algo sobre un nodo (un click, doble click o lo que sea), el JTree le pregunta al TreeCellEditor si se debe comenzar o no la edición, a través del método treeCellEditor.isCellEditable(). Si este método devuelve false, no pasa nada, si devuelve true, comienza la edición.
Si comienza la edición, JTree le pide al TreeCellEditor el Component que hará las veces de editor. Esto lo hace por medio del método treeCellEditor.getTreeCellEditorComponent(). Entre otros parámetros, a este método el JTree le pasa el valor del nodo que se quiere editar. El método crea un Component que haga de editor (por ejemplo, un JTextField) y mete dentro de ese Component el valor que se quiere editar. Devuelve entonces el Component (el JTextField) y JTree se lo presenta a Federico Ratón en la pantalla, para que juegue a sus anchas con el ratón y el teclado.
Como este Component que hace de editor puede ser cualquier cosa que nos inventemos, desde un JTextField hasta un JPanelSuperComplicadoConMilPuñetasDentroYVentanasDesplegables, el JTree se ve incapaz de enterarse él solo cuándo termina la edición. El JTree le pide al TreeCellRenderer que le avise cuando termine la edición. Para eso, llama al método treeCellRender.addCellEditorListener(), pasándole una clase (un CellEditorListener) a la que se debe avisar cuando termine la edición. El TreeCellRenderer debe guardarse esa clase y además debe estar pendiente de su Component que hace de editor. Si Federico Ratón pulsa la tecla de escape (o cualquier otro mecanismo que decidamos para cancelar la edición), el TreeCellRenderer debe avisar al CellEditorListener de que la edición se ha cancelado. Si Federico Ratón mete un montón de datos y pulsa el botón de "Aceptar", o la tecla <intro> o cualquier otro mecanismo que ideemos para validar la entrada, el TreeCellRenderer debe avisar al CellEditorListener que la edición se ha terminado y tenemos un nuevo valor disponible para el nodo.
Cuando el JTree se entera que hay un nuevo valor disponible, se lo pide al TreeCellEditor por medio del método treeCellEditor.getCellEditorValue(). Entonces TreeCellEditor le devuelve el nuevo valor y todos contentos, Federico Ratón ve su nuevo valor en el nodo del árbol.
Bueno, esto tan liado es lo básico. Hay alguna cosilla más que comentaremos por encima, pero no nos preocuparemos demasiado por ello.
Ahora que sabemos lo mínimo imprescindible, vamos a hacer nuestro propio editor.
Vamos a contruir nuestro propio editor con un JComboBox, para que nos quede tal que así
Para contruir nuestro propio TreeCellEditor sólo debemos hacer una clase que implemente TreeCellEditor e implementar todos sus métodos. Vamos a ver qué métodos son esos y cómo implementarlos.
public Component getTreeCellEditorComponent(JTree tree,
Object value, boolean isSelected, boolean expanded, boolean leaf, int row)
public void addCellEditorListener(CellEditorListener l)
public void cancelCellEditing()
public Object getCellEditorValue()
public boolean isCellEditable(EventObject arg0)
public void removeCellEditorListener(CellEditorListener arg0)
public boolean shouldSelectCell(EventObject arg0)
public boolean stopCellEditing()
Listo. Ya sabemos lo que son todos esos métodos y una pequeña idea de cómo implementarlos.
En nuestro ejemplo vamos a poner como editor un JComboBox que permita elegir "abuelo", "padre", "tio", "hijo" e "hija". La implementación de la clase puede ser como esta MiTreeEditor.java.
Un par de detalles nada más:
Para meter este editor en el árbol, basta con hacer la siguiente llamada
tree.setEditable(true);
tree.setCellEditor(new MiTreeEditor());
En PruebaJTree4.java tienes el código completo para crear y visualizar el JTree. Y creo que con esto vale de momento.