I am a little confused by the JTree, JSpinner, their models and their relationship to the applications data model that stores the data it/they display.
When using JTables I make my data model in the manner described below and it is relatively easy to plug that into the JTable.
Do I do the same with a JTree? If so, how?
My data model consists of :
Class : BookManager : Provides methods to manage the contents of an ArrayList that stores Book objects - add, remove, find, get, etc. Class : Book : Provides methods to manage the contents of an ArrayList that stores Chapter objects - add, remove, find, get, etc. Class : Chapter : Provides methods to manage the contents of an ArrayList that stores Scene objects - add, remove, find, get, etc. Class : Scene : Provides getter/setter methods for two String fields - shortDescription and sceneBody.
I can manipulate and edit the data model using menuitems and display the data model in textual form - using the following menu commands..,
add book delete book next book previous book
add chapter delete chapter next chapter previous chapter
add scene delete scene next scene previous scene
I want to use JMenuItems, a JSpinner and JTree in combination as both view and controller of the data model.
I know how to use JMenuItem's to add/remove Books but I don't know how to display these Book titles in the JSpinner. I want to use a JSpinner to select the Book to display in the JTree. I want to use a popup menu on the root node Book to add Chapters to the Book in the JTree. I want to use a popup menu on Chapter nodes to add Scenes to the selected Chapter or delete the selected Chapter ( and all of its Books ). I want to use a popup menu on Scene nodes to delete the selected Scene.
I am really confused by the JSpinner and JTree models that seem to sit between the JSpinner, JTree and my data model - I don't understand how I connect my data model to the JSpinner and JTree via their models.
Can anyone give me a little help.
Thanks [ October 25, 2005: Message edited by: D R Wilkinson ]
Have you looked at the How to Use Trees page in the tutorial? It has a lot of information about working with JTrees. If that doesn't help one of us might be able to offer a suggestion if you can tell more about your Project, Chapter and Scene map. Or give an idea of what you put into a JTable with this.
Thanks for replying. I have included a simplified example of what I am trying to understand and achieve.
In the following example, I can manipulate the data in my data model using the menu items ( I know the data model manipulation is not fault perfect - it is just a quick demo of my problem ).
I want to understand how I can use the JSpinner to control the selection of any given Book within the books ArrayList in BookManager.
When a given Book is selected, I want the JTree to display that Books data ( ie Chapters and Scenes ).
When the root Book icon is selected and right clicked, I want the program to add a chapter icon to the tree that represents the Chapter object that is added to the Books data model - I also want to understand how this chapter icon in the JTree is linked to the Chapter object in the Book data model.
Similar functionality for the chapter icons - basically using the JTree to add, delete, select, etc the objects in the Book data model - instead of using the JMenuItems.
Maybe I am a bit stupid but I do not understand how I link the JSpinner and JTree to my data model and use them to manipulate / display the data models state.
From "How To Use Tree's" - Thus, if the TreeNode interface isn't suitable for your tree model, feel free to devise your own representation for tree nodes. For example, if you have a pre-existing hierarchical data structure, you don't need to duplicate it or force it into the TreeNode mold. You just need to implement your tree model so that it uses the information in the existing data structure.
I am aware that I need to implement the TreeModel and SpinnerModel interfaces somewhere ( possibly in my BookManager class ) but I am not sure if this is correct and if so, then how. I also guess that Listeners are involved in some way but I am unclear as to how and where.
I do not understand how, for example, clicking on a given chapter icon in the JTree selects the associated Chapter object in my Book data model.
Any help would be very welcome. Code follows...
[ October 21, 2005: Message edited by: D R Wilkinson ]
Here's one way you could do it. Notes: 1 — I tried to use the classes you provided with minimal changes. 2 — the classes containing collections have parallel declaration/instantiations for the collections:
one for non–generic j2se 1.4- and
one for generic j2se 1.5+ versions.
It is set up for j2se 1.4-It is set up for j2se 1.4- 3 — the JTree gets the string for each tree node from the 'toString' method in each class.
[ October 22, 2005: Message edited by: Craig Wood ]
Firstly - thank you Craig for writing the example. I really appreciate your effort.
I have been slowly working my way through it and I have some questions.
I have added a "Add Book" menu item which calls a new method addNewBook() that I added to the Books class. This method simply adds a new ModBook to Books List of ModBook objects.
This works fine - a new ModBook is added to the List.
Somehow, the JSpinner must now display this new book.
What I don't understand is how?
By my ( mis ) understanding of how things work..,
Books now stores 2 ModBooks so the data model of the application has changed. The method that made the change ( ie addNewBook() ) should fire some event saying "My state has changed. I have one more new book than before" and the JSpinner ( which is listening for such events ) should go "I hear you Books object, give me your list of ModBooks and I will display them."
When I try to make this happen, I get confused and it doesn't work.
If you could kindly explain how to do this I would be very grateful.
in the actionPerformed method for the addNewBookMenuItem I put the following
so I am...
1. Updating the data model 2. Updating the spinners data model 3. Updating the tree model
which must be wrong as the spinner and tree all ultimately are supposed to be views of the data model, so shouldn't the data model be firing events saying the data has changed and the spinner and tree receiving them and displaying the newly changed data in the data model?
I am finding this to be very confusing [ October 25, 2005: Message edited by: D R Wilkinson ]
the spinner and tree all ultimately are supposed to be views of the data model The JTree is a view of its TreeModel. The JSpinner reflects the state of the the class Books and really has nothing to do with the state of the TreeModel (at least for now). The spinner is used to select ModBooks from the Books class and to then reset the TreeModel (which fires events to reset the tree view) with the new ModBook. You wanted the tree to show only one Book at a time so we have to have a way to bridge the Books class and its client JSpinner with the TreeModel. Let's think about this...
If you change your design to have the TreeModel and JTree have all the ModBooks in Books, as nodes of the root node, then you could easily control everything from within the TreeModel; it would have access to all the ModBooks. You could (dispense with the Books class, let the TreeModel use it or move it into the TreeModel and) let the TreeModel handle the details of the ModBook collection including updates to the JSpinners SpinnerListModel. Or you could let the TreeModel keep the ModBook collection, continue to change the tree root as needed and update the JSpinner.
shouldn't the data model be firing events saying the data has changed and the spinner and tree receiving them and displaying the newly changed data in the data model? In the typical scenario of a JTree whos TreeModel has access to all the data it needs for the tree, yes. With the data model you have elected, not necessarily, possibly. The Books class and its client JSpinner work together to control/change the root of the JTree via its TreeModel. This could be considered as a bit on the radical side but still manageable. The challenge is to find an elegant way to connect the ModBook collection (Books), the selector (spinner) and the TreeModel class. The way it is set up/put together/designed now the TreeModel doesn't care about where the ModBook root comes from. Its only concern is to show the contents of one book at a time. If the TreeModel had access to or contained the collection of ModBooks it could easily change the state of the JSpinner as well as the JTree. Then your JMenuItem action could tell the TreeModel to make the changes in one method call.
If you decide to keep the TreeModel and Books class separate you can make a method to coordinate the changes or leave the code inside the ActionListener as you have it. I wonder if changing the selection state of the JSpinner will automatically message the TreeModel on its own...
About changes to the JSpinner: it works okay to reset the SpinnerListModel of the spinner. A more light–handed approach might be to get its List and add/remove items to/from it. You might then have to call 'fireStateChanged' on the list to get the update sent to the listeners.