第一步:創建帶有分頁功能的TableView
1. 首先我們新建一個Page
類,用來管理數據
- Page.java: 省略getter和setter方法
import javafx.beans.property.SimpleIntegerProperty; import java.util.List; public class Page<T> { private SimpleIntegerProperty totalRecord; // total record number in source data private SimpleIntegerProperty pageSize; // the number of data in per page private SimpleIntegerProperty totalPage; // total page number private List<T> rowDataList; // total data /** setter ** /** getter **/ /** * @param rowDataList * @param pageSize the number of data in per page */ public Page(List<T> rowDataList, int pageSize) { this.totalRecord = new SimpleIntegerProperty(); this.totalPage = new SimpleIntegerProperty(); this.rowDataList = rowDataList; this.pageSize = new SimpleIntegerProperty(pageSize); initialize(); } private void initialize() { totalRecord.set(rowDataList.size()); // calculate the number of total pages totalPage.set( totalRecord.get() % pageSize.get() == 0 ? totalRecord.get() / pageSize.get() : totalRecord.get() / pageSize.get() + 1); // add listener: the number of total pages need to be change if the page size changed pageSize.addListener((observable, oldVal, newVal) -> totalPage.set( totalRecord.get() % pageSize.get() == 0 ? totalRecord.get() / pageSize.get() : totalRecord.get() / pageSize.get() + 1) ); } /** * current page number(0-based system) * * @param currentPage current page number * @return */ public List<T> getCurrentPageDataList(int currentPage) { int fromIndex = pageSize.get() * currentPage; int tmp = pageSize.get() * currentPage + pageSize.get() - 1; int endIndex = tmp >= totalRecord.get() ? totalRecord.get() - 1 : tmp; // subList(fromIndex, toIndex) -> [fromIndex, toIndex) return rowDataList.subList(fromIndex, endIndex + 1); } }
- 這個
Page
類的作用是傳入一個需要分頁的數據(rowDataList)和每頁顯示的行數(pageSize),然后在initialize()
方法中自動計算:數據的總記錄數(totalRecord),總頁數(totalPage)。 - 這里使用了
SimpleIntegerProperty
類,這個類使得我們方便地為變量添加監聽器。
pageSize.addListener((observable, oldVal, newVal) -> totalPage.set( totalRecord.get() % pageSize.get() == 0 ? totalRecord.get() / pageSize.get() : totalRecord.get() / pageSize.get() + 1) );
在程序中,為變量pageSize
添加了一個監聽器,如果pageSize
的值改變,那么總頁數(totalPage)也需要隨之改變。
Page.getCurrentPageDataList(int currentPage)
會根據傳入的頁碼,返回當前頁的數據- 使用泛型,便於組件的重用
2. 添加分頁功能到TableView
- TableWithPaginationAndSorting.java: 省略getter方法
import javafx.collections.FXCollections; import javafx.scene.control.Pagination; import javafx.scene.control.TableView; public class TableWithPaginationAndSorting<T> { private Page<T> page; private TableView<T> tableView; private Pagination tableViewWithPaginationPane; /** getter **/ public TableWithPaginationAndSorting(Page<T> page, TableView<T> tableView) { this.page = page; this.tableView = tableView; tableViewWithPaginationPane = new Pagination(); tableViewWithPaginationPane.pageCountProperty().bindBidirectional(page.totalPageProperty()); updatePagination(); } private void updatePagination() { tableViewWithPaginationPane.setPageFactory(pageIndex -> { tableView.setItems(FXCollections.observableList(page.getCurrentPageDataList(pageIndex))); return tableView; }); } }
- 這個類中最重要的是方法
updatePagination
,這個方法體中設置了Pagination
的頁面工廠,這里使用Lambda表達式傳入一個回調方法,回調方法會在一個頁面被選中時觸發。它會加載並返回被選中頁面的內容。如果當前被選中的頁面索引不存在,則必須返回null值。在這個回調方法中:我們接收傳過來的當前頁碼(pageIndex,從0開始),然后利用Page
對象的getCurrentPageDataList(pageIndex)
方法獲取當頁的數據,轉換格式並添加到TableView
中,最后返回TableView。
關於page factory,可以將它想象成一個加工廠,它負責根據提供的頁碼生產對應的頁面,所以,你可以根據不同的頁碼顯示不同的內容。並且這里我們不用每次都新建一個表格,只需要每次將數據添加到建好了的表格框架
image.png
-
tableViewWithPaginationPane.pageCountProperty().bindBidirectional(page.totalPageProperty());
這一段代碼是將Pagination
的pageCountProperty
和Page
對象的page.totalPageProperty
屬性進行雙向綁定,這樣他們的值就會同步:其中一個改變,另一個也會改變,並且值保持一樣。
如果不使用Lambda,也可以使用匿名函數:
private void updatePagination() { tableViewWithPaginationPane.setPageFactory(new Callback<Integer, Node>() { @Override public Node call(Integer pageIndex) { tableView.setItems(FXCollections.observableList(page.getCurrentPageDataList(pageIndex))); return tableView; } }); }
3. 建立一個測試類
我們先建立一個測試類來測試我們已經開發的功能。
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; import java.util.Arrays; import java.util.List; public class TableWithPaginationAndSortingTest extends Application { @Override public void start(Stage primaryStage) throws Exception { // create table TableView<People> peopleTable = createTable(); // get data List<People> peopleList = getTableData(); peopleTable.setItems(FXCollections.observableList(peopleList)); // create Page object Page<People> page = new Page<>(peopleList, 2); // add pagination into table TableWithPaginationAndSorting<People> table = new TableWithPaginationAndSorting<>(page, peopleTable); Scene scene = new Scene(new BorderPane(table.getTableViewWithPaginationPane()), 300, 300); primaryStage.setScene(scene); primaryStage.show(); } private TableView<People> createTable() { TableView<People> table = new TableView<>(); TableColumn<People, String> nameCol = new TableColumn<>("name"); nameCol.setCellValueFactory(new PropertyValueFactory("name")); TableColumn<People, Integer> ageCol = new TableColumn<>("age"); ageCol.