Forcing the update of a JList - java

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.

Related

Understanding adding a ChangeListener in TableView

I am trying to understand some code from the following source:
http://code.makery.ch/library/javafx-8-tutorial/part3/
The specific line i am still curious about is the following one:
personTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> showPersonDetails(newValue));
I believe that my first understanding of the javadoc was not correct; especially on this part ([...].selectedItemProperty().[...]):
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/SelectionModel.html#selectedItemProperty--
I was asking myself why we are only adding one listener while we may have several dataobjects but now my understanding is the following and it would be nice to know if it is correct:
What the doc means is that "selectedItem" itself is the property (not the underlying data!)which represents a row that is selected/selection-changed at runtime, so the change method of our Listener is then evoked when the user changes the selected row. Then the synchronization with the underlying datamodel takes place via the change(...) method of the ChangeListener Interface, which gets the corresponding dataobjects from the udnerlying datamodel to work on. So from my understanding i would probably raise an exception if i didn't do a correct setItems(...) on my TableView.
Is this correct so far?
If yes, i have got a follow up question: ReadOnlyObjectProperty implements both Observable and ObservableValue which both have the method addListener. Is it correct that the Lambda-Expression is resolved correctly by checking the list of parameters of the two methods of the two possible functional interfaces which could be argument to either one of the addListener(...) methods? That point seemd rather complex to me.
The selectionModel.selectedItemProperty is a ReadOnlyObjectProperty<T> where T is the type of elements in the item list backing your TableView<T>. Whenever a new item is selected in the TableView, the value of the selectedItemProperty changes to refer to the new item. The selected item itself is not a TableRow<T>, it just a reference to the underlying data item which is used render the row. In general, you, as an application programmer, usually don't care about the TableRow which is a visual construct, but only the underlying data. When the user clicks on a row in the table, the TableView implementation sets the selectedItemProperty to the selected data item, that in turn fires any change listeners which have been set on the property.
In the case of the makery example, the T type is Person. So the consequence of this line:
personTable.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> showPersonDetails(newValue)
);
is to invoke the showPersonDetails(Person person) function, passing in the selected person whenever that changes.
So from my understanding i would probably raise an exception if i didn't do a correct setItems(...) on my TableView.
No. If you didn't set any items, the user could never select an item on the table, so you wouldn't ever get an exception from the selected item change listener as the selected item would never change from null and the change listener would never fire.
i have got a follow up question: ReadOnlyObjectProperty implements both Observable and ObservableValue which both have the method addListener. Is it correct that the Lambda-Expression is resolved correctly by checking the list of parameters of the two methods of the two possible functional interfaces which could be argument to either one of the addListener(...) methods?
Yes. How the lambda resolves which method to use which is complicated in compiler implementation, but from an application programmer usability point of view, you can just count the parameters: If it is one parameter, then an InvalidationListener is being defined, if it is 3 parameters, then a ChangeListener is being defined.
There are two addListener(...) methods as it is an overloaded method, one for a ChangeListener and another for an InvalidationListener. The difference between the two is subtle and is explained by the developer of the interfaces with the recommendation: "use a ChangeListener if you need to know the new value in the listener, otherwise use an InvalidationListener".

Add item to OHLCSeries choosing whether notifying/firing data changed

OHLCSeries 'add' method invokes the ComparableObjectSeries class method 'add', which receives a parameter "notify" to indicate whether you want to notify listeners about the change.
My problem is that OHLCSeries 'add' method doesn't has that parameter, so I can't choose between notifying or not, and I need to be able to.
I've tried invoking the 'super' (ComparableObjectSeries) add method from OHLCSeries, but it is not visible.
Any idea on how could I choose when notify listeners and when not, when adding new items?
(I would like to avoid having to override the entire OHLCSeries class or extend it, hoping there is a easier way of doing it)
Since ComparableObjectSeries extends org.jfree.data.general.Series, I've thought on using this class method 'setNotify()' to activate/deactivate notifications to OHLCSeries listeners before invoking the 'add' method.
Even though this solution makes the trick, I'm still interested on how could it be done using a parameter on the 'add' method, directly from OHLCSeries class, so any idea is welcome.

How to create copy of object that can be modified?

I have a list of objects in a Swing GUI. The user can select one and edit the object before having to confirm the change by pressing a button. The state of the object is done with binding.
My problem is; the user should be able to cancel the editing, reverting the changes. The original data is already changed.
I guess I need to have a copy of the object, but I don't know what the correct way is to obtain one. Clone method, copy constructor, serialization,... They all seem to have drawbacks.
This must be a common requirement and I wonder which approach I should use? What is the most elegant way?
One can maintain a history of undoable actions so a list of Undos is possible. Doing an actionPerformed registers the reverse undo action restoring the state.
That would fit nicely.
A bit dated, und/redo essay with patterns.
UndoManager.

JList and ListModel design pattern advice

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.

How can I give a component more than one DropTargetListener?

I just learned (the hard way) that Java Components can only have one DropTarget. No sweat, I said, I'll just add another DropTargetListener to that DropTarget--only to discover that DropTargets can only have one DropTargetListener!
I have two DropTargetListeners that listen for very different events (one handles things being dragged and dropped within the component, the other handles things from outside the component). Must I combine them into one giant DropTargetListener, or is there an elegant way to keep them separate?
DropTarget is a unicast source, so you can add at most one DropTargetListener to it. I believe it should be a simple object that examines the source (inside/outside) of the thing being dropped and calls one of your DropTargetListeners depending on the result.
Edit: If you are hell bent on creating a "universal" solution, then you might try creating a wrapper event that passes method calls to the original event, but intercepts rejectDrop(), acceptDrop() (and maybe other methods that can cause trouble), then pass the wrapper to your listeners, until one accepts it. This assumes that the listeners recognize "good" events and act accordingly.
If you don't find a satisfactory solution, you could use the Composite Pattern to create a DropTargetListener that has a list of child DropTargetListeners. Whenever one of its methods are called, it would iterate over its list of listeners and invoke the same method. That would allow you to hand a single DropTargetListener to the Component but still have multiple DropTargetListeners called.

Categories