JList and ListModel design pattern advice - java

I am building an application which is basically just a GUI for displaying and editing one single object. Since the class for this object was created with JAXB, it is basically a tree with many Strings and integers as children, but there are also some List<E>s. For each simple child JAXB provides a getter and a setter, but for all lists only a getter is provided, since it gives a reference to the internal list, which can now be modified.
Since I need to display every child (and branch for that matter) in a separate swing GUI component, I need these views to handle some data. According to my current knowledge about the model view controller design pattern, I should strictly separate the model from the view. Following this, it would be a bad idea to let a JList operate directly on an internal list of my base object. (Actually doing so would be a pretty easy solution to my specific use case, but since additional functionality might be added later on, I think I should refrain from this idea.)
Then I started thinking: If I do not let the components work on the list directly, I have to make them use a copy of the original. But since I cannot set the original list to a new one returned by my GUI component, I have to copy the items another time when saving the view data to my model. Also, it would not be wise to hand out references to internal lists of a custom ListModel, which would mean, that depending on the depth of the GUI structure, the list may be copied additional times.
Since I also want my application to be efficient, this does also not seem like the correct approach. How do I build this "correctly"?
Summary:
The List<E> from the original object is a reference to an internal list of
the object.
The JList displaying the list should not get this reference,
hence it must copy the list.
Getting the list from the JListshould not yield in a
reference to the internal list either, hence it must be copied again.
Saving the list to the original object must copy the list a third
time, because the original object does not have a setter method for the list. (see
above for details)
Is my grasp on this correct? How do I build this properly and make it efficient?
P.S: Adding setter methods to the original class structure is not an option!

was created with JAXB, it is basically a tree with many Strings and
integers as children, but there are also some List<E>s. For each
simple child JAXB provides a getter and a setter, but for all lists
only a getter is provided, since it gives a reference to the internal
list, which can now be modified.
see
JTreeTable
JList (unmodifiable), better could be JTable (with / without JTableHeader) in JTree

All of the components suggested by #mKorbel provide some kind of selection listener that will allow you to loosely couple a selection in one panel to the selected item's display in another. FileBrowser illustrates a TreeSelectionListener; Outline can have a ListSelectionListener, shown here; etc.
Addendum: In this related example, DisplayPanel listens to an adjacent TableModel, which it can query to update a model in one of it's own components. Note that each model is loosely coupled to its respective view. Common notification mechanisms are mentioned here.

Related

Why Swing Components have .getParent() method, Is it violated Object Oriented Principles?

I am working on Object Oriented Design Principles and Heuristics.
In the remarkable book named Object-Oriented Design Heuristics By Arthur J. Riel (1996) I see this heuristic:
Heuristic 4.13: A class must know what it contains, but it should never know who contains it.
Based on J.Reil, The main reason is reusability.
But in Swing Structure, we can access directly to the reference of Parent object.
for example: label.getParent()
So my question is:
Why swing components have .getParent() method?
Which Object Oriented Priciples or Heuristics are behid of existing this method?
Two things here: no rules are cast in stone in software engineering. It is always about balancing different aspects that are somehow competitive.
Then: the main purpose of UI components is (surprise) to be used in UIs. And typically any UI element belongs to exactly one parent. You can't have the same table showing up in two windows (maybe the same data, but not the UI table objects!). And from there: getting to the parent of a UI component is something that you need all the time. UI elements are always owned - and it is much more convenient when you can go up and down easily.
Long story short: I think you are looking at a very special case here - where it simply makes a lot of sense to deviate from a rule written in some book.
Disclaimer: I haven't read the book in question, so I can only speculate on what the author meant.
But my surmise would be that what is intended here is that the class should not change its behavior based on the type of the class that contains it. So, a Button must not behave differently when it's in a ScrollPane than it does if it is in a JPanel or a JFrame.
But the hierarchy of components in the UI is part of their responsibilities. They are in a tree structure, and so they not only maintain links to one another, but they have accessors to allow client code to navigate that structure. Now, you could have a structure where only the parents had links to the children, and not vice versa, just as you could have a singly-linked list. But to have a doubly-linked list, where each node has a pointer, not only the the node after it, but also a pointer back to the node before it, is not a violation of object-oriented principles, and neither is it a violation to have a doubly-linked tree structure where the child nodes also have pointers that allow navigating up the tree, from children to parents.
We must ask ourselves, how would knowing who contains it impair reusability? Why would knowing that make the class less reusable? Now, if it changed its behavior based on who contained it, that would do it. You could not just take the class and use it somewhere else, because it might not do what you expect it to do. But merely maintaining the links doesn't harm reusability.
(I would note that, if you're going to add and remove components from the hierarchy, there has to be some care taken in their API so that when you tell one of them you're severing the link, both of them can update their state. But that can be handled as part of the API design. As long as that was done up front in the first version so that it's part of the contract of all classes that are written to be part of that component hierarchy, it would not pose a problem.)

Does wicket tree work for "not direct" children?

Hey I have following situation:
Class Foo has a List of Foos,
Every Foo contains one or more Objects of the Class Bar and has therefore a List Bars.
Every Bar has one or more Objects of Qux, which is another class and because of that is safed in a List named Quxs.
Is it even possible to loop through these Lists / Sets with a Wicket TableTree, TreeTable, DefaultTreeTable or whatever else.
Right now I'm trying to solve this with 3 nested ListViews, which seems not to be the best solution.
Because if you have to use a ListView, whitin a ListView of ListView, it is difficult to get the Object you are refering to.
The decision whether to use ListViews or one of the Tree components should really be made based on the desired look&feel (ie. possible user interactions like opening/closing nodes in a tree). It is definitely possible to present your nested list with its three different classes in a tree (though you may not be able to take advantage of Java generics in this case, unless all the classes have some suitable common interface).
The ITreeProvider interface is a good place to start, if you want to build your own tree structure (https://ci.apache.org/projects/wicket/apidocs/7.x/org/apache/wicket/extensions/markup/html/repeater/tree/ITreeProvider.html).

Handling large number of Swing components

I'm doing a favor for an engineer friend by making him a program that helps him with the scheduling of his factory's production. Each type of product is broken down to a set of steps (they share a lot of them, but there are a few differences).
The programming issue:
Each time a new production process is registered I display a number of checkboxes representing the before mentioned steps. He can choose which steps he needs added for this particular product. If he checks a checkbox, two (or more) textfields appear where he can add additional information (starting date, duration, comments, etc...). My problem is that this is a lot of individual components and I am unsure how to handle them. Since I will need to have access to all of them at some point (the checkboxes to see if that step is needed and all the textfields for the data) I was thinking of having them all as fields, but that doesn't feel right...
Another approach could be to make a container class that groups the textfields together with the checkbox. Something like this:
ArrayList<MyComponentGroup> group;
for (MyComponentGroup cg : group) {
if (cg.getCheckBox().isSelected()) {
//access and read the data from all the textfields in this object
}
}
What is the Java programming convention or the most commonly used method to handle this situation?
Here's what I would do when dealing with tons of components and similar requirements:
I would model the relationship between options (available through checkbox selections) and the related data to fill (requirements). This model may already be available for you.
I would attempt to use PropertyEditor instances and map them to model elements.
When the time comes to save or use the data filled by the user, I would just walk the model represented on the screen, grab the associated editors and deal with the value of those editors.
I think that the approach that I described above will give you less work and potentially and it will bring more flexibility for your friend.
You'd only pay the initial cost of getting the components relationships/dependencies in a nice model as well as registering the relevant PropertyEditors for visual editing.
One approach is to consistently give each JComponent a unique name. Use something hierarchical to fit the complex process, like "Whites.Rinsecycle.enableCB". For completeness, store this String as a clientProperty in the JComponent. Then you can use that as a key in a large Map to access all the components.
Maybe not the most "elegant" (I'd tend to go with a hierarchy of JPanels with relevant fields) but for a slightly quick and dirty, moderate sized project this is reasonable.

Forcing the update of a JList

When I edit the quantity of an object in a list and the toString changes, how do I get the list to update with the new toString?
Example, when I change nodes in my JTree, I use nodeChanged(node) what do I do when I change a list item?
AbstractListModel#fireContentsChanged if you extend from AbstractListModel.
It is the same principle as for the JTree of your previous question. The AbstractListModel does not know when some internal property of your objects is changed. So when you make a change, you must call that particular method indicating the object is changed. The list model will fire the correct event which is received by the JList, which will update/repaint (whatever you want to call it).
Personally I prefer to create ListModels which are self-contained, e.g. if the objects you use fire events when they change the ListModel can listen for those changes and fire the appropriate events itself instead of having to call this method externally.
Edit
Just noticed that that particular method is protected, so you need to create the model as I suggested and you cannot call that method externally (which is a good thing)
List.updateUI() will do it, although I'm told this has some overhead.

How to change JTree view dynamically when a nodes object's state changes?

I'm implementing a Java JTree panel. This panel holds a TreeModel build from a set ofdatastructures that are treelike (a list of lists of composites - different classes). I get these datastructure from external jar implementations based on a set of interfaces I defined.
The treenodes contain a checkbox that the user may check to indicate that the checked node and all child nodes are to become "active", that is, the objects that are represented by the nodes should do something, like getting data from a database.
The treenodes may also be selected without "activating" them, that is, without the checkbox being checked.
On top of that, other parts of the program may also toggle the activation state of the datamodel objects. So the data model out of which the treemodel is build is the source of the activation state. This must be reflected in the treeview by dynamically (un)checking the checkbox.
Now, how do I implement this whole? Who should be listeners for what changes?
I now have all the classes that are in the nodes extend from an abstract class that holds an activation field. This is the true datasource. When this field changes, all subscribed listeners (EventListener) should be notified, This includes the checkboxes.
I also have a TreeSelectionModel that is based on the default TreeSelectionModel but extended with functionality to check if children/parents need to be checked.
My questions maybe is not really clear, but so is this complex piece of code. Hope you can help.
You seem to have a bunch of moving parts. It might be good to funnel all changes through your TreeModel, and have yourJTree be the listener, as it will be automatically. If your TreeModel is a subclass of DefaultTreeModel, you get a host of fire* (fireTableStructureChanged, fireTreeNodesChanged, etc.) methods which will alert your JTree to repaint. Make sure you do this firing of events in the AWT EventQueue.
here is a good tutorial with a load of examples for using Trees.
Check out the jide components. It includes a checkboxtree also:
It sounds to me like you have the right idea -- make the node the canonical source for the "activated" knowledge, and the canonical source of activation events. Then you can have the TreeModel listen to that and translate those events into fireTreeNodesChanged() etc, which should cause the JTree to update itself automatically.
To keep yourself out of trouble, try to keep the node -> tree event relationship one way -- that is, don't use the tree as a controller, don't allow tree events to change the activation state.

Categories