JavaFX TableView: collect data from visible columns only - java

I want to put the data from a TableView into a Collection of Maps. Each Map represents a row in the table and contains the columnName-entry-pairs of all visible columns.
Now the tricky part for me is to get the data from the visible columns only.
On the TableView, I could call getItems(), but how could I then check which column is visible?
With getColumns(), I can check which column is visible, but how could I then get the corresponding data?
The easiest thing would be a way to iterate through all visible columns - but I can't find a way to do this.
Can anyone give me a hint or a pointer in the right direction?

You can try this, though I did not test this:
final ObservableList<Map<String, Object>> collection = FXCollections.observableArrayList();
tableView.getItems().forEach(item -> {
final Map<String, Object> itemMap = new HashMap<>();
tableView.getVisibleLeafColumns().forEach(column -> {
itemMap.put(column.getText(), column.getCellObservableValue(item).getValue());
}
collection.add(itemMap);
});

Related

How do i convert Array

I am trying to serialize Observable Maps with an Serialiazation Proxy.
These two properties need to be saved.
private final MapProperty<Integer, Cargo> allCargoStoredMap;
private final MapProperty<Cargo, CargoLogisticData> cargoLogisticDataMap;
I thought i can save the values in an array like this:
this.cargoLogisticDataAsArray = warehouseManagement.getCargoCargoLogisticDataMap().values().toArray(new CargoLogisticData[0]);
this.cargoAsArray = warehouseManagement.getAllCargoStoredMapProperty().values().toArray(new Cargo[0]);
Then i want to pass i to an Constructor, and rebuild the properties.
public Constructor (List<Cargor> cargos, List<CargoLogisticData>) {
ObservableMap<Integer, Cargo> cargos = FXCollections.observableHashMap();
//How do i add my cargos to a map?
this.allCargoStoredMap = new SimpleMapProperty<>(cargos);
}
Any Idea how i can add the the List Entrys to my map?
I thought i maybe have to save 4 Arrays. Two with key, two with values. And then add those again.
Any Ideas ?
This can be a simple solution if I don't get it wrong
allCargoStoredMap.values().stream().forEach(cargo -> {
CargoLogisticData logisticsData=cargoLogisticDataMap.get(cargo);
/*
You have cargo and related logistics data here.
You can create which data model you want to store and use it
*/
})

JavaFX unfilter FilteredList

I have got a ObservableList and I linked it to multiple CheckMenuItem it's shown in a TableView and I can filter out one predicate.
I did that by using .filter(Predicate p) and updated my TableView to it's return value. When I wanted to unfilter, I simply set it back on my ObservableList.
But I can't wrap my head around on how to remove multiple filteres to my ObservableList. I can apply them if i just keep using .filter(Predicate p) with different predicates on the returned lists, but how to I remove a spcific filter?
Greets
The code
ObservableList<DataType> data = FXCollections.observableArrayList();
table.setItems(data.filter(predicate));
is equivalent to
ObservableList<DataType> data = FXCollections.observableArrayList();
table.setItems(new FilteredList<DataType>(data, predicate));
and the code
ObservableList<DataType> data = FXCollections.observableArrayList();
table.setItems(data.filter(predicate1).filter(predicate2));
is logically equivalent to
ObservableList<DataType> data = FXCollections.observableArrayList();
table.setItems(new FilteredList<DataType>(data, predicate1.and(predicate2)));
So you can achieve what you need by keeping a reference to the filtered list and updating its predicate:
ObservableList<DataType> data = FXCollections.observableArrayList();
FilteredList<DataType> filteredData = new FilteredList<>(data, x -> true);
table.setItems(filteredData);
Now you can use predicate1 only with:
filteredData.setPredicate(predicate1);
add predicate2:
filteredData.setPredicate(predicate1.and(predicate2));
remove predicate1:
filteredData.setPredicate(predicate2);
remove all filters:
filteredData.setPredicate(x -> true);
If you wanted a really esoteric solution (which is almost certainly overkill), you could keep an ObservableList<Predicate<DataType>>:
ObservableList<Predicate<DataType>> filters = FXCollections.observableArrayList();
and then bind the predicate of the filtered list to combining all filters with a logical and:
filteredList.predicateProperty().bind(Bindings.createObjectBinding(() ->
filters.stream().reduce(x -> true, Predicate::and),
filters));
Then you can just add and remove predicates to the filters list, e.g.
filters.add(predicate1);
filters.add(predicate2);
filters.remove(predicate1);
and the table data will automatically update.

How to sort a TableView programmatically?

I want a certain column of a TableView to be sorted by default. How would I do this? I tried doing column.setSortType(SortType.ASCENDING);, as well as putting it in a runLater call. I looked at the JavaDocs and stuff and all I can see that may be of interest is the peculiar setSortPolicy method.
To perform a "one-off" sort, call
tableView.getSortOrder().setAll(...);
passing in the TableColumn(s) by which you want the data sorted.
To make the sort persist even as the items in the list change, create a SortedList and pass it to the table's setItems(...) method. (To change the items, you will still manipulate the underlying list.)
As an example, using the usual contact table example you could do:
TableView<Person> table = new TableView<>();
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
TableColumn<Person, String> lastNameCol = new TableColumn<>("
Last Name");
firstNameCol.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
ObservableList<Person> data = FXCollections.observableArrayList();
SortedList<Person> sortedData = new SortedList<>(data);
// this ensures the sortedData is sorted according to the sort columns in the table:
sortedData.comparatorProperty().bind(table.comparatorProperty());
table.setItems(sortedData);
// programmatically set a sort column:
table.getSortOrder().addAll(firstNameCol);
// note that you should always manipulate the underlying list, not the sortedList:
data.addAll(new Person(...), new Person(...));
Called at the end of the table initialisation...
colChecked.setSortType(TreeTableColumn.SortType.DESCENDING);
colDate.setSortType(TreeTableColumn.SortType.DESCENDING);
treeView.getSortOrder().setAll(colChecked, colDate);

Fitler JTable of contents of an ArrayList

I have a simple library application, and one thing it needs to accomplish is checkout/return books. In that checkout/return window, I have two tables, a "Book List" table, which starts full of books I already have stored, and a "Checkout/Return" table, which starts out empty. The Checkout/Return table is populated by double clicking items in the Book List table, and then depopulated by double clicking items displayed within itself. Double clicking adds or removes the book items to/from a checkout/return ArrayList (which is then displayed in the table).
What I'm looking for is a way to filter out books in the Book List table by the contents of the Checkout/Return ArrayList. (Unable to post images of desired effect at this time).
Is this even possible, and if so, how similar is this to filtering by the contents of a JTextField?
Edit: I've since found this approach: http://pulkitsinghal.blogspot.com/2010/06/multiple-row-filters-for-jtable.html.
RowFilter<TableModel, Object> firstFiler = null;
RowFilter<TableModel, Object> secondFilter = null;
List<RowFilter<TableModel,Object>> filters = new ArrayList<RowFilter<TableModel,Object>>();
RowFilter<TableModel, Object> compoundRowFilter = null;
try {
firstFiler = RowFilter.regexFilter(yourRegexString, columnIndex);
secondFilter = RowFilter.regexFilter(yourRegexString, columnIndex);
filters.add(firstFiler);
filters.add(secondFilter);
compoundRowFilter = RowFilter.andFilter(filters); // you may also choose the OR filter
} catch (java.util.regex.PatternSyntaxException e) {
return;
}
sorter.setRowFilter(compoundRowFilter);
However, this achieves the opposite affect I want. Rather than filtering out everything that doesn't match the filter input, I want to filter out everything that does match the filter input.

Fast aggregation of multiple ArrayLists into a single one

I have the following list:
List<ArrayList> list;
list.get(i) contains the ArrayList object with the following values {p_name=set1, number=777002}.
I have to create a
Map<key,value>
where the key contains the p_name, and values are the numbers.
How to do it easily and fast as there can be hundreds of entries in the initial list and each number can be present in multiple p_name entries.
Update: Here is my current solution
List<Row> list; //here is my data
Map<String,String> map = new TreeMap<String,String>();
for (Row l : list) {
if (l.hasValues()) {
Map<String, String> values = l.getResult(); // internal method of Row interface that returns a map
String key = values.get( "number");
map.put(key, values.get( "p_name" ));
}
}
The method works, but maybe it could be done better?
PS : There is an obvious error in my design. I wonder if you find it :)
Sine the key can have more then one values, what you are looking for is a MultiMap. Multimap
Or a simple map in the form
Map<Key,ArrayList<Values>>
There is no "fast" way here to me. You still need to iterate through all the elements and check all the values.
And actually hundreds to Java is not much at all

Categories