JavaFX TableView 分页器

Posted

技术标签:

【中文标题】JavaFX TableView 分页器【英文标题】:JavaFX TableView Paginator 【发布时间】:2013-02-27 06:07:31 【问题描述】:

在TableView分页器中如何使用.?.举个例子...

public class SampleController implements Initializable 

    @FXML private TableView<Student> table;
    @FXML private TableColumn<Student, Integer> id;
    @FXML private TableColumn<Student, String> name;
    @FXML private ObservableList<Student> list = FXCollections.observableArrayList();
    //  @FXML private Pagination pagination;
    // 
    private StudentSQL ssql = new StudentSQL();
    private Stage stage = new Stage();
    private String row;

    @Override
    public void initialize(URL url, ResourceBundle rb) 
        id.setCellValueFactory(new PropertyValueFactory<Student, Integer>("id"));
        name.setCellValueFactory(new PropertyValueFactory<Student, String>("name"));
        list = ssql.students();
        table.setItems(list);
    

【问题讨论】:

【参考方案1】:

这里是一些将 TableView 与分页控件集成的示例代码。

代码来自 Shakir Quasaroff 对 Oracle JavaFX 论坛请求 PaginatedTableView 控件的回答。示例代码是纯 Java 解决方案,而不是原始问题中的 Java 代码/FXML 混合。

import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.Node;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TablePager extends Application 

    final ObservableList<Person> data = FXCollections.observableArrayList(
            new Person("1", "Joe", "Pesci"),
            new Person("2", "Audrey", "Hepburn"),
            new Person("3", "Gregory", "Peck"),
            new Person("4", "Cary", "Grant"),
            new Person("5", "De", "Niro"),
            new Person("6", "Katharine", "Hepburn"),
            new Person("7", "Jack", "Nicholson"),
            new Person("8", "Morgan", "Freeman"),
            new Person("9", "Elizabeth", "Taylor"),
            new Person("10", "Marcello", "Mastroianni"),
            new Person("11", "Innokenty", "Smoktunovsky"),
            new Person("12", "Sophia", "Loren"),
            new Person("13", "Alexander", "Kalyagin"),
            new Person("14", "Peter", "OToole"),
            new Person("15", "Gene", "Wilder"),
            new Person("16", "Evgeny", "Evstegneev"),
            new Person("17", "Michael", "Caine"),
            new Person("18", "Jean-Paul", "Belmondo"),
            new Person("19", " Julia", "Roberts"),
            new Person("20", "James", "Stewart"),
            new Person("21", "Sandra", "Bullock"),
            new Person("22", "Paul", "Newman"),
            new Person("23", "Oleg", "Tabakov"),
            new Person("24", "Mary", "Steenburgen"),
            new Person("25", "Jackie", "Chan"),
            new Person("26", "Rodney", "Dangerfield"),
            new Person("27", "Betty", "White"),
            new Person("28", "Eddie", "Murphy"),
            new Person("29", "Amitabh", "Bachchan"),
            new Person("30", "Nicole", "Kidman"),
            new Person("31", "Adriano", "Celentano"),
            new Person("32", "Rhonda", " Fleming's"),
            new Person("32", "Humphrey", "Bogart"));
    private Pagination pagination;

    public static void main(String[] args) throws Exception 
        launch(args);
    

    public int itemsPerPage() 
        return 1;
    

    public int rowsPerPage() 
        return 5;
    

    public VBox createPage(int pageIndex) 
        int lastIndex = 0;
        int displace = data.size() % rowsPerPage();
        if (displace > 0) 
            lastIndex = data.size() / rowsPerPage();
         else 
            lastIndex = data.size() / rowsPerPage() - 1;

        

        VBox box = new VBox(5);
        int page = pageIndex * itemsPerPage();

        for (int i = page; i < page + itemsPerPage(); i++) 
            TableView<Person> table = new TableView<Person>();
            TableColumn numCol = new TableColumn("ID");
            numCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("num"));

            numCol.setMinWidth(20);

            TableColumn firstNameCol = new TableColumn("First Name");
            firstNameCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("firstName"));


            firstNameCol.setMinWidth(160);

            TableColumn lastNameCol = new TableColumn("Last Name");
            lastNameCol.setCellValueFactory(
                    new PropertyValueFactory<Person, String>("lastName"));

            lastNameCol.setMinWidth(160);

            table.getColumns().addAll(numCol, firstNameCol, lastNameCol);
            if (lastIndex == pageIndex) 
                table.setItems(FXCollections.observableArrayList(data.subList(pageIndex * rowsPerPage(), pageIndex * rowsPerPage() + displace)));
             else 
                table.setItems(FXCollections.observableArrayList(data.subList(pageIndex * rowsPerPage(), pageIndex * rowsPerPage() + rowsPerPage())));
            


            box.getChildren().add(table);
        
        return box;
    

    @Override
    public void start(final Stage stage) throws Exception 

        pagination = new Pagination((data.size() / rowsPerPage() + 1), 0);
        //   pagination = new Pagination(20 , 0);
        pagination.setStyle("-fx-border-color:red;");
        pagination.setPageFactory(new Callback<Integer, Node>() 
            @Override
            public Node call(Integer pageIndex) 
                if (pageIndex > data.size() / rowsPerPage() + 1) 
                    return null;
                 else 
                    return createPage(pageIndex);
                
            
        );

        AnchorPane anchor = new AnchorPane();
        AnchorPane.setTopAnchor(pagination, 10.0);
        AnchorPane.setRightAnchor(pagination, 10.0);
        AnchorPane.setBottomAnchor(pagination, 10.0);
        AnchorPane.setLeftAnchor(pagination, 10.0);
        anchor.getChildren().addAll(pagination);
        Scene scene = new Scene(anchor, 400, 250);
        stage.setScene(scene);
        stage.setTitle("Table pager");
        stage.show();
    

    public static class Person 

        private final SimpleStringProperty num;
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;

        private Person(String id, String fName, String lName) 
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.num = new SimpleStringProperty(id);
        

        public String getFirstName() 
            return firstName.get();
        

        public void setFirstName(String fName) 
            firstName.set(fName);
        

        public String getLastName() 
            return lastName.get();
        

        public void setLastName(String fName) 
            lastName.set(fName);
        

        public String getNum() 
            return num.get();
        

        public void setNum(String id) 
            num.set(id);
        
    
   

示例程序输出:


此外,第三方 lgpl 许可 TiwulFX library by Panemu 为 TableView 提供高级功能(包括分页)。

【讨论】:

这个写入成为控制器类? 不,这个答案中的解决方案不是基于 fxml,它与 Controller 类无关。 我认为提供的示例包含许多不必要的代码并且做了不必要的工作。为什么要为每个页面重新创建 tableView?为什么 a 在 for 循环中创建?请参阅我的答案以获取已清理的版本。无意冒犯。 不错的优化提姆。【参考方案2】:

您必须使用Pagination 控件并实现页面工厂。每个应该显示的页面都会调用该工厂,您可以使用其参数 pageIndex 为 TableView 提供项目的子列表:

TableView table = ...

private Node createPage(int pageIndex) 

    int fromIndex = pageIndex * rowsPerPage;
    int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
    table.setItems(FXCollections.observableArrayList(data.subList(fromIndex, toIndex)));

    return new BorderPane(table);



@Override
public void start(final Stage stage) throws Exception 

    Pagination pagination = new Pagination((data.size() / rowsPerPage + 1), 0);
    pagination.setPageFactory(this::createPage);
    ...

可以在此处找到完整的可运行示例: https://gist.github.com/timbuethe/7becdc4556225e7c5b7b

【讨论】:

嗨!感谢您提供使用 JavaFX 创建页面的方法。但是,我在测试您的代码时发现了一个小问题(这也适用于@jewelsea)。当数据的大小 == 到一个页面中设置的行数时,会发生混乱(页面内)。在这种情况下,会创建一个额外的(空白)页面,并且数据拒绝显示在任何页面上。所以,我想出了一个快速的解决方案来解决这个问题。希望能帮助到你!有关代码 sn-p,请参阅我的帖子。 :) 我很奇怪 createPage 返回一个新的 BorderPane。这对我来说没有意义,你只是想更新表格内容。【参考方案3】:

我在测试这个线程产生的分页代码时发现了一个小问题。当数据的大小 == 到一个页面中设置的行数时,会发生混乱(页面内)。在这种情况下,会创建一个额外的(空白)页面,并且数据拒绝显示在任何页面上。我相信以下 sn-p 应该可以解决该问题(如果其他人遇到与我相同的问题)。这个 sn-p 应该在声明 Pagination 变量之前。

int numOfPages = 1;
if (data.size() % rowsPerPage == 0) 
  numOfPages = data.size() / rowsPerPage;
 else if (data.size() > rowsPerPage) 
  numOfPages = data.size() / rowsPerPage + 1;

Pagination pagination = new Pagination((numOfPages), 0);
pagination.setPageFactory(this::createPage);

希望对你有帮助!

【讨论】:

以上是关于JavaFX TableView 分页器的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX TableView分页 - 无法创建基于fxml的解决方案

ant-vue中table自定义分页器

ant-vue中table自定义分页器

具有垫表初始化的角度材料2分页器

javaFX tableView中嵌入

如何将elementUI 表格(el-table)和分页器(el-pagination)连接起来