Modifying AdministratorFrame
The frame now needs to show AnimalPanel inside a new tab of the JTabbedPane:
At this point you can run the application to ensure it appears as below:
You can double-click the Animals node on the left to expand it, and then click the Pen sub-nodes that appear to see the animals in that pen. To make all the nodes expanded when you start the application add the following method inside AnimalTree:
- The
getRowCount()method simply returns the total number of nodes in the tree, whileexpandRow()forces the specified node to be expanded.
Now call expandNodes() from the constructor:
You will note that after entering some details and clicking the Save button the added animal is not appearing in the list on the left. This will be addressed in the next section.
Updating AnimalTree automatically
For the AnimalTree object to get notified whenever a change to the collection of animal objects held by the administrator changes it can implement the AnimalListener interface, so you will need to import virtualzoo.core.event:
If you click the glyph that appears to the left of the class declaration statement above, you can click the option to implement all abstract methods. The following code will appear:
To handle the animalCreated() method first, insert the following code:
- Firstly, a new
DefaultMutableTreeNodeis created for the newAnimal - Then the
Penit should be in is determined - The
Penis passed as an argument togetTreeNode()(a method to be written shortly) which will return the node which relates to thePen - The
insertNodeInto()method is invoked on the model to cause the new animal to appear in the tree - The tree is then rebuilt in order that the nodes are correctly sorted
The getTreeNode() method loops through each of the nodes under the root node until it finds the one in the argument, which it then returns:
- An
Enumerationis an alternative way of iterating over a group. ThehasMoreElements()method returnstrueif there are more elements to process, and thenextElement()method returns the next element to be processed
You now need to wire up the AnimalTree object which is referenced in AnimalPanel so that it listens to events. In AnimalPanel import virtualzoo.core and define a new instance variable to reference the ZooAdministrator object:
Now change the constructor to obtain the ZooAdministrator object and call its addAnimalListener() method:
You can now run the application, enter, and save one (or several) animals, and you should find the tree automatically updates itself.
Modifying existing animal details
Now that you have completed the code necessary to add new animals you need to enable their details to be changed. What you will do is detect whenever the user selects one of the names in AnimalTree and pass that selected Animal object to AnimalEditor so that it transitions into "change" mode.
The JTree class (of which AnimalTree is a subclass) supports the fact that client objects may wish to listen to selections of nodes in the tree. All client objects need to do is implement the TreeSelectionListener interface and provide the appropriate code in its required valueChanged() method. Then you can pass the client object as an argument to the addTreeSelectionListener() method of JTree. You will now code these steps.
Firstly, change the class header of AnimalPanel to implement TreeSelectionListener (you will also need to import the java.swing, javax.swing.event and javax.swing.tree packages):
Now you need to code the only method required by the interface:
- The
valueChanged()method will be called every time the user selects an any node in the tree, which could be either an animal, a pen, or the root node - The
getLastSelectedPathComponent()method retrieves the selectedObject. This will benullif nothing is actually selected so it is tested to ensure that it is notnullbefore continuing. Provided it is notnullthen it is checked to ensure that an animal node was selected, and if so, this gets cast fromObjecttoAnimal(any other type of node will be ignored) - You then pass the
Animalobject to thesetAnimal()method ofAnimalEditor, which you coded earlier
You need to ensure you listen to the tree selection events so invoke the registration in the constructor:
In AnimalTree you need to ensure the tree is updated: