JavaFX tree view showing default selection - java

I am using JavaFX8.
I have a tree view and it contains some objects.
The tree view gets displayed with all the nodes expanded.
I would like to have a default item on the treeview selected when the UI startsup.
I have tried the following but it doesn't work.
rootNode.setExpanded(true);
popupTree.setShowRoot(false);
popupTree.setRoot(rootNode);
popupTree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
popupTree.requestFocus();
popupTree.getSelectionModel().select(new TreeItem<FinancialAccount>(selectedAccount));
popupTree.getFocusModel().focus(popupTree.getSelectionModel().getSelectedIndex());
If I replace the code with a static integer value like this
popupTree.requestFocus();
popupTree.getSelectionModel().select(5);
popupTree.getFocusModel().focus(5);
This selects the 5th item on the tree and its highlighted on the UI.
To determine the index of the object in the tree, I am using the methods in my first snippet, they always return -1
Obviously the select(object) method in the SelectionModel class is not correctly evaluating the passed object. I tried overriding the equals method in my FinancialAccount Object but it doesn't make a difference.
Any thoughts on how to get this working

Related

Label visibility on filtered list search in JavaFX

I'm using a TextField with a listener to filter a TableView. I've got if statements that set the predicate if newText matches part of the ID or Name.
The search functionality works like I want.
However, my project guidelines require me to also create some form of output upon a search not matching any objects in the TableView.
I created a Label and set the visibility to false to start. I placed the code to set the Label to visible after each of the if statements in the predicate logic so that it only shows if none of the statements are valid. I then placed a line setting it back to false at the beginning of the predicate logic so on each listener change it gets reset.
I am having an issue where if my search returns the last item in the list it is fine and the label doesn't appear, but if the search doesn't return the last item in the list then the label becomes visible even though the search displays items from the sorted list.
The following is my code and I've attached screenshots of the "bug".
FilteredList<Part> filteredParts = new FilteredList<>(Inventory.getAllParts(), p -> true);
partFilter.textProperty().addListener((ob, ol, newValue) -> {
filteredParts.setPredicate(text -> {
//each time listener is updated sets label visibility to false
partSearchMismatch.setVisible(false);
//If searchbar is empty or null it displays all parts
if (newValue == null || newValue.isEmpty()){
return true;
}
//if text matches partID
String lowerCaseFilter = newValue.toLowerCase();
if(String.valueOf(text.getId()).contains(lowerCaseFilter)){
return true;
}
//if text matches part name
if(text.getName().toLowerCase().contains(lowerCaseFilter)){
return true;
}
partSearchMismatch.setVisible(true); //if no matches, displays label
return false; //no match
});
});
//Wraps filtered list in sorted list
SortedList<Part> sortedParts = new SortedList<>(filteredParts);
//Binds sorted list comparator to the parts table comparator
sortedParts.comparatorProperty().bind(partsTable.comparatorProperty());
partsTable.setItems(sortedParts);
The following is the base sample data in table
Image of search that matches first object in list but label showing anyways
Image of search that matches second object in list but label showing anyways
Image of label working as long as last object in table is included in search
my project guidelines require me to also create some form of output upon a search not matching any objects in the TableView.
That will happen by default, when the filtered table does not have any matches for the filter, the table will display a placeholder. The placeholder node is configurable, so you can set it display anything you want.
You don't need an additional label and logic to show that nothing would be displayed in the table unless you have an additional requirement for that.
Okay, so it's the placeholder text that I see in the table that says "no content in table"? I should just be able to set that to something that mentions the search didn't return anything. Thank you. I am still curious what I am doing wrong with the label though
The predicate is a boolean function, it should be executed without side effects. You set the predicate on the filtered list, but you don't know or have any control over when the filtered list will choose to execute that code. The predicate may be executed many times to filter each individual item in the list. If you put side effects in the predicate like setting label visibility, you don't really know what will happen unless the operations are idempotent (they aren't).
Instead, have the predicate evaluate the lambda input object to see if it should be filtered or not, only returning true or false and doing nothing else.
That you name the input parameter to the predicate as text indicates that you don't really understand it. The input parameter is a Part, an element of the observed list, it is not text, so it would make sense to name it part and not text. Also (and this is just style, not functional), to help make the code easier to read, use a descriptive name for the new text in the listener (e.g. filterText or newSearchText rather than newValue).
For a concrete example of searching a table using a filtered list and a text field, see, the Eden Coding tutorial:
Search bar with predicates.
As noted by Slaw in comments:
If the placeholder is not enough, I would try to use bindings.
Something like:
label.visibleProperty().bind(
Bindings.isEmpty(filteredParts)
.and(
partFilter.textProperty().isNotEmpty()
)
)
);
Or you can move the logic for the label notification setting out of the predicate but keep it in the change listener for the search text field (this essentially does a similar job to the binding).

Uniquely representing tree elements

I want to make my TreeView remember the selected items after refresh/setInput. (Let's pretend the Java TreeView doesn't remember the state). Since the TreeView will get setInput, so the element reference won't persist.
I am thinking to store the selected element by its full path in an ArrayList<String>. (e.g. it looks like ["root_name", "2nd_level_name", "3rd_level_name", "node_name"]). With the full path, I can locate the same element in the refreshed TreeView again.
I was wondering if there's any better way doing this? Or any existing libraries in Java can do this?

Accessing elements of an object in a jList/listModel

I'm trying to populate a jList, I want it to display a name but also store an ID (which is not displayed) for each item in the list.
I have created a list model and added each element as an object. The object holds an int value (the ID) and a string value (the name):
doorListModel.addElement(nextDoor);
Once all the elements have been added I then send this model to the jList:
jList1.setModel(doorListModel);
When you run the program the jList appears to just show a memory location for each element:
How can I get the jList to just display the String value and, (assuming this is possible) how do I access the hidden int value if I was to select an item from the jList.
Cheers.
You've got two options as I see it:
You can give your Door class a decent toString() method since this is what the JList displays by default, or
Give your JList a decent ListCellRenderer. This is the recommended solution since a toString() result really shouldn't be used for production purposes but rather for debugging.

Adding data to a tree-view-list

I've started to use the tree-view-list to show my data. The tree-view-list can be found here:
http://code.google.com/p/tree-view-list-android/
The code that adds text to the tree view line is this:
private String getDescription(final long id) {
final Integer[] hierarchy = getManager().getHierarchyDescription(id);
return "Node " + id + Arrays.asList(hierarchy);
}
in the SimpleStandardAdapter.java file. The data shown in the demo is based on the row id and nothing external to the treeview.
How would I go about adding text for a line of the tree that is external to the tree view?
For example, an array of data that is filled at run time.
The adapter (pretty much as any other adapter) build views from the data provided by model. The AbstractTreeViewAdapter is written in the way that it provides implementation for a wrapped view - so it will either create a new child view (abstract getNewChildView) or reuse one (updateView) - and then adds it as a sub-view to cell item with the right padding/margin etc. (this provides automatically indenting in the tree).
So whenever you need to display something in your own way as a tree cell, you should build your own adapter (you can either extend SimpleStandardAdapter or build your own Adapter from the scratch in similar way to SimpleStandardAdapter and return appropriate view that you want to display as result of getNewChildView and updateView methods.
Both methods get TreeNodeInfo treeNodeInfo as parameter, so you can figure out which node of the tree you are about to render. The type is - unfortunately - not changeable, I tried at the beginning to make a generic solution where you will be able to use any object type but failed at that, and it has to be Long. Probably it should be changed to reflect that.
So you will get the Long id from TreeNodeInfo that will identify the node, and the best way to use it is to use the Long value as index to some Map where you will keep reference to your node's object(s) and this way to know which data to render.
I hope it helps.

Finding the node where an instance belong

I generated a decision tree based on a set of data, then I converted this data to a xml file, after that I put it into a JTree. This part works fine but now I have to take a new instance(which contains the data received from the user), find it's place in the decision tree and change that node's color. And I can't find a way to do that. I am using weka and the J48 classifier to generate the decision tree. The xml is created in the Luc Sorel style: http://www.lucsorel.com/media/downloads/sample_decision_tree.xml
The first thing I tried was to classify the instance using the algorithm but that gets me only the class where it belongs, and I don't know how to locate it in the JTree.
What should I do? Any ideeas?
Like JTable, JTree uses a flyweight renderer to draw nodes. As the default renderer is a JLabel, you can set the foreground color or make the label opaque and set the background color. This related example changes the icon for emphasis. More examples may be found here.
Addendum: I cannot find … the node that I should color.
When getTreeCellRendererComponent() is called, value is a reference to the node to be rendered, and the tree parameter allows access to the TreeModel as a whole via getModel(). This example shows how to search a tree.

Categories