How to sort a TableView programmatically? - java

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);

Related

DynamoDB: Batch query items with highest range key given a set of hash key

I have a table Book with bookId and lastBorrowed as hash and range keys, respectively.
Let's say each time a book is borrowed, a new row is created.
(Yes, this is NOT sufficient and I can just add a column to keep track of the count and update lastBorrowed date. But let's just say I'm stuck with this design there's nothing I can do about it.)
Given a set of bookIds (or hashKeys), I would like to be able to query the last time each book is borrowed.
I attempted to use QueryRequest, but kept getting com.amazonaws.AmazonServiceException: Attempted conditional constraint is not an indexable operation
final Map<String, Condition> keyConditions =
Collections.singletonMap(hashKeyFieldName, new Condition()
.withComparisonOperator(ComparisonOperator.IN)
.withAttributeValueList(hashKeys.stream().map(hashKey -> new AttributeValue(hashKey)).collect(Collectors.toList())));
I also tried using BatchGetItemRequest, but it didn't work, either:
final KeysAndAttributes keysAndAttributes = new KeysAndAttributes() .withConsistentRead(areReadsConsistent);
hashKeys.forEach(hashKey -> { keysAndAttributes.addExpressionAttributeNamesEntry(hashKeyFieldName, hashKey); });
final Map<String, KeysAndAttributes> requestedItemsByTableName = newHashMap();
requestedItemsByTableName.put(tableName, keysAndAttributes);
final BatchGetItemRequest request = new BatchGetItemRequest().withRequestItems(requestedItemsByTableName);
Any suggestion would be much appreciated!
Or if someone can tell me this is currently not supported at all, then I guess I'll just move on!
You can do this, in fact its very easy. All you have to do is execute a Query for your bookId and then take the first result.
By the way, your table design sounds absolutely fine, the only problem is the attribute should probably be called borrowed rather than last borrowed.
You can have multiple results for a single bookId, but because lastBorrowed is your range key, the results will come back ordered by that attribute.
You seem to be using Legacy Functions, are you editing old code?
If not, execute your Query something like this:
//Setting up your DynamoDB connection
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_WEST_2).build();
DynamoDB dynamoDB = new DynamoDB(client);
Table table = dynamoDB.getTable("YOURTABLE");
//Define the Query
QuerySpec spec = new QuerySpec()
.withKeyConditionExpression("bookId = :book_id)
.withValueMap(new ValueMap()
.withString(":book_id", "12345")
.withScanIndexForward(true);
//Execute the query
ItemCollection<QueryOutcome> items = table.query(spec);
//Print out your results - take the first item
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}

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.

JavaFX TableView: collect data from visible columns only

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);
});

How add Items to Tableview Javafx 8 without Creating Class

I'm learning JavaFX 8 and working on Tableview.
I know we can add data to table view by using following steps.
ObservableList<PersonCode> data =
FXCollections.observableArrayList(
new PersonCode("Jacob", "Smith"),
new PersonCode("Isabella", "Johnson"),
new PersonCode("Ethan", "Williams"),
new PersonCode("Emma", "Jones"),
new PersonCode("Michael", "Brown")
);
Then set Column cellValueFactory
TableColumn<PersonCode, String> firstName = new TableColumn<PersonCode, String>("First Name");
firstName.setCellValueFactory(new PropertyValueFactory<PersonCode, String>("aName"));
TableColumn<PersonCode, String> lastName = new TableColumn<PersonCode, String>("Last Name");
lastName.setCellValueFactory(new PropertyValueFactory<PersonCode, String>("aNameLast"));
and then table.setItems(data);
But my question is, can we add data to table's column without creating another class? As in my previous example I have created PersonCode class. But I want to add following data to tableview.
ObservableList<String> data = FXCollections.observableArrayList("Good","Luck","Bad");
As I was reading Tableview Doc there I found this line.
When you create a table in a JavaFX application, it is a best practice
to implement a class that defines the data model and provides methods
and fields to further work with the table. Example 13-3 creates the
Person class to define data in an address book.
So I'm expecting we can add data without creating a separate class. How? any idea?

How to delete row from table column javafx

These are my table columns Course and Description. If one clicks on a row (the row becomes 'active'/highlighted), and they press the Delete button it should remove that row, how do I do this?
The code for my Course column: (and what event listener do I add to my delete button?)
#SuppressWarnings("rawtypes")
TableColumn courseCol = new TableColumn("Course");
courseCol.setMinWidth(300);
courseCol.setCellValueFactory(new PropertyValueFactory<Courses, String>("firstName"));
final Button deleteButton = new Button("Delete");
deleteButton.setOnAction(.....
Just remove the selected item from the table view's items list. If you have
TableView<MyDataType> table = new TableView<>();
then you do
deleteButton.setOnAction(e -> {
MyDataType selectedItem = table.getSelectionModel().getSelectedItem();
table.getItems().remove(selectedItem);
});
If someone want to remove multiple rows at once, there is similar solution to accepted:
First we need to change SelectionMethod in our table to allow multiple selection:
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
After this, we need to set action with such code for button:
ObservableList<SomeField> selectedRows = table.getSelectionModel().getSelectedItems();
// we don't want to iterate on same collection on with we remove items
ArrayList<SomeField> rows = new ArrayList<>(selectedRows);
rows.forEach(row -> table.getItems().remove(row));
We could call removeAll method instead of remove(also without creating new collection), but such solution will remove not only selected items, but also their duplicates if they exists and were not selected. If you don't allow duplicates in table, you can simply call removeAll with selectedRows as parameter.

Categories