0

I am working on a JavaFX application which requires handling large amount of data. I am using tableview with pagination so that user can page through all data easily.

When I click on tableview column header the default sorting gets applied on the data, that is fine, but the sorting is applied to data on current page only not to the entire data. I want the sorting to be applied to all the data and then the data in the current page to be changed according to the sorted data.

The data comes from a Rest API call in one go and fills an Observable list which backs up the tableview. The tableview page contains only a subset of data from the backing list and sorting is applied to that only, but I want the whole backing list to be sorted and data on the page to be changed according to sorted data.

This is how I create pages:

private void setPullBackDocumentData() {
    // TODO Auto-generated method stub
    paginationPullbackList = new Pagination();
    paginationPullbackList.setPageCount(Utils.getPageCount(data.size(), Common.rowsPerPage));
    paginationPullbackList.setCurrentPageIndex(0);
    paginationPullbackList.setPageFactory(this::createPage);
    setTableData();
    vBoxContent.getChildren().clear();
    vBoxContent.getChildren().add(new BorderPane(paginationPullbackList));
}

private Node createPage(int pageIndex) {

    int fromIndex = pageIndex * Common.rowsPerPage;
    int toIndex = Math.min(fromIndex + Common.rowsPerPage, data.size());
    tableViewDocumentList.setItems(FXCollections.observableArrayList(data.subList(fromIndex, toIndex)));
    Utils.setTableViewCellSize45(tableViewDocumentList);
    return new BorderPane(tableViewDocumentList);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private void setTableData() {
    // TODO Auto-generated method stub
    tableViewDocumentList = new TableView<DocumentPullBack>();
    tableViewDocumentList.setEditable(true);
    tableViewDocumentList.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    TableColumn documentNameCol = new TableColumn(
            Utils.getStringFromResourceBundle("pullback.table.document.name"));
    documentNameCol.setCellValueFactory(new PropertyValueFactory<DocumentPullBack, String>("finalDocumentName"));

    TableColumn stateCol = new TableColumn(Utils.getStringFromResourceBundle("pullback.table.state"));
    stateCol.setCellValueFactory(new PropertyValueFactory<DocumentPullBack, String>("documentStateName"));

    TableColumn pullBackDateCol = new TableColumn(
            Utils.getStringFromResourceBundle("pullback.table.pullback.date"));
    pullBackDateCol.setStyle("-fx-alignment: CENTER;");
    pullBackDateCol.setCellValueFactory(new PropertyValueFactory<DocumentPullBack, Date>("pullbackDateTimeAsDate"));
    pullBackDateCol.setCellFactory(
            new Callback<TableColumn<DocumentPullBack, Date>, TableCell<DocumentPullBack, Date>>() {
                @Override
                public TableCell<DocumentPullBack, Date> call(TableColumn<DocumentPullBack, Date> param) {

                    TableCell<DocumentPullBack, Date> cell = new TableCell<DocumentPullBack, Date>() {
                        @Override
                        public void updateItem(Date item, boolean empty) {
                            if (empty) {
                                setGraphic(null);
                            } else {
                                DocumentPullBack currentDocument = (DocumentPullBack) getTableView().getItems()
                                        .get(getIndex());
                                String date = "";
                                date = DateUtils.convertToLocal(currentDocument.getPullbackDateTime());

                                setText(date);
                            }
                        }
                    };
                    return cell;
                }
            });

    pullBackDateCol.setComparator(Comparator.nullsFirst(Comparator.naturalOrder()));
    //pullBackDateCol.sortTypeProperty().addListener(o -> System.out.println("sortType changed to: " + pullBackDateCol.getSortType()));
    
    //tableViewDocumentList.setItems(data);
    tableViewDocumentList.getColumns().clear();
    tableViewDocumentList.getColumns().addAll(documentNameCol, /* sourceCol, */stateCol, pullBackDateCol);
}

I referred to answer here question on filtering and sorting, but it seems to observe pagination's page index property, and in my case this will not change since we are not filtering any data just sorting the same data. I have tried applying sortPolicy and tried to work on getSortOrder(), but with no luck. Is there a way I can achieve this?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Amit Patel
  • 37
  • 1
  • 5
  • [mcve] please (with hard-coded data) to demonstrate what's not working as expected – kleopatra Apr 28 '21 at 12:46
  • 2
    Maybe this will help? http://incepttechnologies.blogspot.com/p/javafx-tableview-with-pagination-and.html – Abra Apr 28 '21 at 13:10

1 Answers1

0

I think the best approach is to figure out the pagination in the data somehow, and then implement the page in the data model for the TableView line items. Then you can use the Predicate property of a filtered list to control the table contents by page:

public class Paginator extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        ObservableList<LineItem> lineItems = FXCollections.observableArrayList();
        lineItems.add(new LineItem("One", "Page 1, 1", 1));
        lineItems.add(new LineItem("Two", "Page 1, 2", 1));
        lineItems.add(new LineItem("Three", "Page 2, 1", 2));
        lineItems.add(new LineItem("Four", "Page 2, 2", 2));
        lineItems.add(new LineItem("Five", "Page 3, 1", 3));
        lineItems.add(new LineItem("Six", "Page 3, 2", 3));
        lineItems.add(new LineItem("Seven", "Page 4, 1", 4));
        primaryStage.setScene(new Scene(new PageView(lineItems)));
        primaryStage.show();
    }

    class PageView extends BorderPane {

        private IntegerProperty currentPage = new SimpleIntegerProperty(1);
        private Predicate<LineItem> filter = lineItem -> true;

        PageView(ObservableList<LineItem> items) {
            TableView<LineItem> tableView = new TableView<>();
            TableColumn<LineItem, String> titleColumn = new TableColumn<>("Title");
            titleColumn.setCellValueFactory(new PropertyValueFactory<LineItem, String>("title"));
            TableColumn<LineItem, String> descColumn = new TableColumn<>("Description");
            descColumn.setCellValueFactory(new PropertyValueFactory<LineItem, String>("desc"));
            tableView.getColumns().addAll(titleColumn, descColumn);
            Button nextButton = new Button("Next");
            nextButton.setOnAction(evt -> currentPage.set(currentPage.get() + 1));
            Button prevButton = new Button("Prev");
            prevButton.setOnAction(evt -> currentPage.set(currentPage.get() - 1));
            setCenter(tableView);
            setBottom(new HBox(20, prevButton, nextButton));
            FilteredList<LineItem> filteredList = new FilteredList<>(items);
            filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> createPredicate(), currentPage));
            tableView.setItems(filteredList);
        }

        Predicate<LineItem> createPredicate() {
            System.out.println("Creating Predicate");
            return lineItem -> lineItem.pageProperty().get() == currentPage.get();
        }


    }

    public class LineItem {
        StringProperty title = new SimpleStringProperty("");
        StringProperty desc = new SimpleStringProperty("");
        IntegerProperty page = new SimpleIntegerProperty(1);

        public LineItem(String title, String desc, int page) {
            this.title.set(title);
            this.desc.set(desc);
            this.page.set(page);
        }

        public StringProperty titleProperty() {
            return title;
        }

        public StringProperty descProperty() {
            return desc;
        }

        public IntegerProperty pageProperty() {
            return page;
        }
    }
}
DaveB
  • 1,836
  • 1
  • 15
  • 13