Understanding adding a ChangeListener in TableView - java

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".

Related

javafx - Custom Control - How to handle text events and apply predicates generically. (got stuck in middle)

This is updated version of the question javafx-TableView as combobox popup (Tried and able to achieve partially. need help further)
Based on few inputs I got here and referred some existing custom controls (controlsFX), I started implementing my custom control and achieved most of it but got stuck in middle. So need your support.
I have attached my whole project here for reference.
Let me explain my requirement first.
My real application consists of around 40 to 50 text fields in the scene. Suggesstions should be poped up, based of the text typed by the user in the text fields and user should select something using keyboard and able to tab out to the next text field. The suggesstion popup should be a table view with 2 or more columns. The search can be applied on any 1 column or all columns which should be configured by the user while instantiating the control. Please see the screen shot for your reference.
Now what I have achieved.
I have created a CustomControl with 2 classess which will show a popup with a table view inside below the configured node.
**TableViewPopup.java extends PopupControl
TableViewPopupSkin.java implements Skin<TableViewPopup<T>>**
refering AutoCompletePopup.java and AutoCompletePopupSkin.java from controlsFX project.
This is working as expected (atleast most of the functionalities).
Then I should be able to attach the TableViewPopup to a TextField.
So I created another CustomControl with 2 classess
SearchableTextField.java extends TextField
SearchableTextFieldSkin.java extends TextFieldSkin
So this is the control user will add it to their scene finally and tell this control what tableviewpopup should be displayed when the text changes.
Till here everything works fine.
Where I got stuck or what I want to do?
<SearchableTextField fx:id="personSearchableTextField" referenceDataControlNameToLoad="/view/PersonReferenceDataTableView" />
<SearchableTextField fx:id="vehicleSearchableTextField" referenceDataControlNameToLoad="/view/VehicleReferenceDataTableView" />
In the above code snippet, I have 2 instances of my SearchableTextField each shows 2 different TableViewPopup(one with Person and other with Vehicle).
Now I want to apply different predicates to the tableview's filtered list as the user started typing in the text field.
I have attached a textChangedListener which is inside the SearchableTextFieldSkin class. First of all I dont know how to get the filtered list inside the textChangedListener (Please advice is there any better way.) but somehow I'm referring the filtered list but dont know how to apply the predicates bcoz it may be any different enitties (in my case it may be Person entity or Vehicle entity).
I dont want to check the instances hard coded bcoz in my real application i have around 150 entities.
I also dont want the predicates related logic inside the SearchableTextFieldSkin class. means, i want all my different predicates in a separate file and just want to call them.
Or atleast somehow route the filtering logic from the SearchableTextFieldSkin class.
Please suggest a way and a better way. I really concerened about performance bcoz what i am doing is a c# with dev express components project that i am currently rewriting in java using javafx bcoz the performance is worse like anything in c#.
Thanks in Advance.
I would be trying to keep the Predicates close to, or inside, the controller that needs to use them. PersonController should deal with Person predicates, VehicleController with the Vehicles ones, and also with any logic for deciding which fields are searched etc.
There are a few ways to do what I'm thinking, but they all boil down to passing the search field text back through to the IGenericReferenceDataController implementation, which resets the Predicate on the FilteredList.
You could expose a StringProperty on IGenericReferenceDataController to track the filter text. A helper class that encapsulates the FilteredList and the Predicates for a particular controller, exposes the filterText property and handles the logic for resetting it would be better as that should be fairly generic code that you can plug into the IGenericReferenceDataController keeping it all isolated. Something along the lines of:
public interface FilterHelper {
public StringProperty filterTextProperty();
// any methods to assign filters for columns etc. such as
public void assignCurrentFilter(...);
... etc ...
}
Then get IGenericReferenceDataController to expose it's instance of this class:
public interface IGenericReferenceDataController extends IGenericController {
public FilteredList<?> getInnerTableViewControlDataSource();
public FilterHelper getFilterHelper();
}
You would need to pass that out through TableViewPopupSkin and TableViewPopup until it finally gets to SearchableTextFieldSkin where you can have:
private void registerListeners() {
tableViewPopup.getFilterHelper().filterTextProperty().bind(sourceSearchableTextField.textProperty());
...
}
Your FilterHelper implementation then handles resetting the filter on the list every time the search text changes and SearchableTextField knows nothing.
If there is a faster way to get from SearchableTextFieldSkin to IGenericReferenceDataController you could cut out some of the intermediary methods that just pass the reference along, but I couldn't see any in your code and I don't use fxml so I have no idea what magic might be possible there.

Vaadin 7 Combo Box - how to populate and dropdown when text is typed?

I have an app that has editors for various database records. These records are referencing each other. I'm developing a new custom data-aware component that is based on ComboBox:
public abstract class CustomDbLookupField<T> extends CustomField<T> implements Field<T>
Here is what I want:
the component looks like a combo box (I could do this easily)
when the corresponding field has a row id value, then the component displays the textual representation of that referenced record (I could also do this)
when the user starts typing text in the combobox, then I want to search for keywords in the database, and populate the combobox with those items, and let then
drop down the combo box for him and et him select from the results
I cannot seem to do the last two parts. I wanted to bind listener to the "text typed into combo box" event, but I cannot find any method for that. Moreover, I don't know how to get the text that was just typed in. I was trying this:
cmb.addListener(com.vaadin.event.FieldEvents.TextChangeEvent.class,target, method);
but I don't know what to pass for parameters target and method.
That's a good question, and one that cannot be answered in a few sentences. I'll try to give you a short answer upfront and will try to elaborate more on this later. I'm currently hacking a small example to demonstrate the feature you want to achieve. But I'll need some more time. I'll update my answer as soon as I have some results.
Until then, the short answer to your question is that if you register a listener for TextChangeEvents on a component, you'll need someone to actually fire these events. This typically happens on the client side, for example in a TextField. When you derive from CustomField you still need to provide some client side implemenation. CustomField is only a base implementation for your custom field implementation without an awful lot of ready-to-go client side functionality. So, in your case, the listener for TextChangeEvents will actually never be invoked.
You can do a lot easier by deriving from ComboBox. ComboBox already has built-in support for prefix filtering when typing in text into the ComboBox. The actual filter functionality is implemented in the Container which is data source to the ComboBox. The trick is to overwrite protected method ComboBox#getOptionsWithFilter(boolean) to filter in the database and use a custom Container implementation which provides the filtered items from the database.
Update: As promised, I have written a small demo application which shows how you can write a custom ComboBox whose items are dynamically populated from the database as the user types in text. This can be achieved with a simple hack by deriving from ComboBox and overwriting method com.vaadin.ui.ComboBox.buildFilter(String, FilteringMode). The overridden method will need to return a custom Container.Filter implementation that simply carries over the current filter String to a custom com.vaadin.data.Container implementation. The container is then responsible for fetching the filtered items from the database and populating itself with the query result. In my example, I derive from BeanItemContainer where I do the custom database filtering in the overridden method de.oio.vaadin.SuggestingContainer.addFilter(Filter)
You can check out the demo at my GitHub project. Don't hesitate to ask if there is anything unclear.

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 to Use Java Observer's update(Observable, Object) Function?

I have a basic MVC pattern created in Java that uses the Observable/Observer class/interface.
Observable Observer Observable/Observer
Model Controller View
View triggers an event to the Controller, when the user interacts with the GUI.
- E.g presses a button, fills in a field, etc.
Model triggers an event to the View when it updates its state.
- E.g when the a button was pressed and the Controller requests new results.
My question is about the Observer function
update(Observable obs, Object arg);
This is one function, but I have many different kinds of updating to do in my View for example. How do I elegantly distinguish between an update to, say, my search results or the displaying of additional information? These are two completely different updates that use different objects from the Model.
My first idea was to use the Object to pass a string which would describe what update is required.
"UpdateResults" "DisplayAdditionalInformation" "AddQuestions"
but that seems error-prone and ugly. My second instinct was to create an EventObject that would be passed as an Object, but then I have to keep asking what kind of EventObject I'm using:
if (arg instanceof ResultEventObject)
// Get results from model
else if (arg instanceof InformationEventObject)
// Get information from model
else if (arg instanceof QuestionsEventObject)
// get questions from model
My third idea is to simply update everything, but that seems pointlessly inefficient.
I am probably not understanding the Observable/Observer interface correctly or I'm not using update() as it was intended by it's authors. Therefore my question, how do I use the updatefunction properly when I have many different types of updates or events to process?
You can create your own Listener interfaces depending on what view/model you are listening to. This allows your view/model to pass exactly the information required to your controller and will make it easier to unit test the controller.
For listening to the model, updating everything is the simplest solution and you can do that unless performance proves to be an issue.
Yes, I think its better to use Listener Interface
check this note http://www.softcoded.com/web_design/java_listeners.php

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.

Categories