带分页的 JavaFX TableView 过滤(一起) [英] JavaFX TableView Filtering with Pagination (Together)

查看:25
本文介绍了带分页的 JavaFX TableView 过滤(一起)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我分别对TableViewFilteringPagination做了一些研究.

过滤:

在细节中--------------
我尝试先实现分页功能,结果奏效了,
其次,当我开始输入 TextField 过滤器功能时,将匹配/过滤 ObservableList 中的数据,然后根据匹配的数据大小重新排列分页并通过像 Datatable 的搜索和分页那样的表格,这就是我想要的,但我失败了

我的代码...

PersonTableController.java

public class PersonTableController {@FXML 私有 TextField filterField;@FXML 私有 TableView人表;@FXML 私有 TableColumnsl 列;@FXML 私有 TableColumn名字列;@FXML 私有 TableColumn姓氏列;@FXML 私有分页分页;私有 ObservableListmasterData = FXCollections.observableArrayList();私有整数数据大小;私人 int rowsPerPage = 4;公共 PersonTableController() {masterData.add(new Person(1, "Hans", "Muster"));masterData.add(new Person(2, "Ruth", "Mueller"));masterData.add(new Person(3, "Heinz", "Kurz"));masterData.add(new Person(4, "Cornelia", "Meier"));masterData.add(new Person(5, "Cornelia", "Meier"));masterData.add(new Person(6, "Werner", "Meyer"));masterData.add(new Person(7, "Lydia", "Kunz"));masterData.add(new Person(8, "Anna", "Best"));masterData.add(new Person(9, "Stefan", "Meier"));masterData.add(new Person(10, "Hans", "Muster"));masterData.add(new Person(11, "Ruth", "Mueller"));masterData.add(new Person(12, "Heinz", "Kurz"));masterData.add(new Person(13, "Werner", "Meyer"));masterData.add(new Person(14, "Lydia", "Kunz"));}@FXML私有无效初始化(){dataSize = masterData.size();pagination.currentPageIndexProperty().addListener(new ChangeListener() {@覆盖public void changed(ObservableValue observable, Number oldValue, Number newValue) {changeTableView(newValue.intValue(),rowsPerPage);}});FilteredListFilteredData = new FilteredList<>(masterData, p -> true);filterField.textProperty().addListener((observable, oldValue, newValue) -> {过滤数据.setPredicate(人 - > {if (newValue == null || newValue.isEmpty())返回真;String lowerCaseFilter = newValue.toLowerCase();如果 (person.getFirstName().toLowerCase().indexOf(lowerCaseFilter) != -1) {返回真;//过滤匹配名字.}返回假;//不匹配.});});SortedList<人>sortedData = new SortedList<>(filteredData);sortedData.comparatorProperty().bind(personTable.comparatorProperty());//personTable.setItems(sortedData);slColumn.setCellValueFactory(new PropertyValueFactory("sl"));firstNameColumn.setCellValueFactory(new PropertyValueFactory("firstName"));lastNameColumn.setCellValueFactory(new PropertyValueFactory("lastName"));int totalPage = (int) (Math.ceil(dataSize * 1.0/rowsPerPage));pagination.setPageCount(totalPage);pagination.setCurrentPageIndex(0);changeTableView(0,rowsPerPage);}私有无效changeTableView(整数索引,整数限制){int fromIndex = 索引 * 限制;int toIndex = Math.min(fromIndex + limit, dataSize);列表<人>subListObs = masterData.subList(fromIndex, toIndex);ObservableListtmpObsToSetTableVal = FXCollections.observableArrayList();personTable.getItems().clear();personTable.setItems(null);对于(人 t:subListObs){tmpObsToSetTableVal.add(t);}personTable.setItems(tmpObsToSetTableVal);}}

Person.java

public class Person {私人最终 IntegerProperty sl;私人最终 StringProperty firstName;私人最终 StringProperty 姓氏;公共人(整数 sl,字符串名字,字符串姓氏){this.sl = new SimpleIntegerProperty(sl);this.firstName = new SimpleStringProperty(firstName);this.lastName = new SimpleStringProperty(lastName);}公共整数 getSl() {返回 sl.get();}公共无效 setSl(整数 sl){this.sl.set(sl);}公共字符串 getFirstName() {返回 firstName.get();}public void setFirstName(String firstName) {this.firstName.set(firstName);}公共字符串 getLastName() {返回 lastName.get();}public void setLastName(String lastName) {this.lastName.set(lastName);}}

Main.java

public class Main extends Application {@覆盖公共无效开始(阶段primaryStage){primaryStage.setTitle("分页和过滤");尝试 {FXMLLoader loader = new FXMLLoader(Main.class.getResource("PersonTable.fxml"));AnchorPane 页面 = (AnchorPane) loader.load();场景场景=新场景(页面);primaryStage.setScene(场景);primaryStage.show();} catch (IOException e) {e.printStackTrace();}}公共静态无效主(字符串 [] args){发射(参数);}}

PersonTable.fxml

<?import javafx.scene.control.Pagination?><?import javafx.scene.control.TableColumn?><?import javafx.scene.control.TableView?><?import javafx.scene.control.TextField?><?import javafx.scene.layout.AnchorPane?><?import javafx.scene.layout.HBox?><AnchorPane minWidth="315.0" prefHeight="400.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="PersonTableController"><儿童><HBox id="HBox"alignment="CENTER" spatial="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"><儿童><Label text="过滤表:"/><TextField fx:id="filterField" prefWidth="-1.0" HBox.hgrow="ALWAYS"/></儿童></HBox><TableView fx:id="personTable" prefHeight="-1.0" prefWidth="-1.0" tableMenuButtonVisible="false" AnchorPane.bottomAnchor="60.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="40.0"><列><TableColumn fx:id="slColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="SL"/><TableColumn fx:id="firstNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="First Name"/><TableColumn fx:id="lastNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="Last Name"/></列><columnResizePolicy><TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/></columnResizePolicy></TableView><HBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"><儿童><分页 fx:id="分页"/></儿童></HBox></儿童></AnchorPane>

任何帮助:) plz

解决方案

这是我对您的问题的简单解决方案:

import javafx.beans.property.IntegerProperty;导入 javafx.beans.property.SimpleIntegerProperty;导入 javafx.beans.property.SimpleStringProperty;导入 javafx.beans.property.StringProperty;导入 javafx.collections.FXCollections;导入 javafx.collections.ObservableList;导入 javafx.collections.transformation.FilteredList;导入 javafx.collections.transformation.SortedList;导入 javafx.fxml.FXML;导入 javafx.fxml.Initializable;导入 javafx.scene.control.Pagination;导入 javafx.scene.control.TableColumn;导入 javafx.scene.control.TableView;导入 javafx.scene.control.TextField;导入 java.net.URL;导入 java.util.ResourceBundle;公共类控制器实现可初始化{@FXML私人文本字段过滤字段;@FXML私有 TableView人表;@FXML私有表列<人,整数>sl 列;@FXMLprivate TableColumn名字列;@FXMLprivate TableColumn姓氏列;@FXML私人分页分页;私有静态最终 int ROWS_PER_PAGE = 4;私有 ObservableListmasterData = FXCollections.observableArrayList();private FilteredList过滤数据;@覆盖公共无效初始化(URL 位置,ResourceBundle 资源){设置数据();FilteredData = new FilteredList<>(masterData, p -> true);filterField.textProperty().addListener((observable, oldValue, newValue) -> {过滤数据.setPredicate(人 ->新值 == 空 ||newValue.isEmpty() ||person.getFirstName().toLowerCase().contains(newValue.toLowerCase()) ||person.getLastName().toLowerCase().contains(newValue.toLowerCase()));changeTableView(pagination.getCurrentPageIndex(), ROWS_PER_PAGE);});slColumn.setCellValueFactory(data -> data.getValue().slProperty().asObject());firstNameColumn.setCellValueFactory(data -> data.getValue().firstNameProperty());lastNameColumn.setCellValueFactory(data -> data.getValue().lastNameProperty());int totalPage = (int) (Math.ceil(masterData.size() * 1.0/ROWS_PER_PAGE));pagination.setPageCount(totalPage);pagination.setCurrentPageIndex(0);更改表视图(0,ROWS_PER_PAGE);pagination.currentPageIndexProperty().addListener((observable, oldValue, newValue) ->changeTableView(newValue.intValue(), ROWS_PER_PAGE));}公共无效设置数据(){masterData.add(new Person(1, "Hans", "Muster"));masterData.add(new Person(2, "Ruth", "Mueller"));masterData.add(new Person(3, "Heinz", "Kurz"));masterData.add(new Person(4, "Cornelia", "Meier"));masterData.add(new Person(5, "Cornelia", "Meier"));masterData.add(new Person(6, "Werner", "Meyer"));masterData.add(new Person(7, "Lydia", "Kunz"));masterData.add(new Person(8, "Anna", "Best"));masterData.add(new Person(9, "Stefan", "Meier"));masterData.add(new Person(10, "Hans", "Muster"));masterData.add(new Person(11, "Ruth", "Mueller"));masterData.add(new Person(12, "Heinz", "Kurz"));masterData.add(new Person(13, "Werner", "Meyer"));masterData.add(new Person(14, "Lydia", "Kunz"));}私有无效changeTableView(整数索引,整数限制){int fromIndex = 索引 * 限制;int toIndex = Math.min(fromIndex + limit, masterData.size());int minIndex = Math.min(toIndex,filteredData.size());SortedList<人>sortedData = 新的 SortedList<>(FXCollections.observableArrayList(filteredData.subList(Math.min(fromIndex, minIndex), minIndex)));sortedData.comparatorProperty().bind(personTable.comparatorProperty());personTable.setItems(sortedData);}类人{私人最终 IntegerProperty sl;私人最终 StringProperty firstName;私人最终 StringProperty 姓氏;公共人(整数 sl,字符串名字,字符串姓氏){this.sl = new SimpleIntegerProperty(sl);this.firstName = new SimpleStringProperty(firstName);this.lastName = new SimpleStringProperty(lastName);}公共 int getSl() {返回 sl.get();}公共整数属性 slProperty() {返回 sl;}公共字符串 getFirstName() {返回 firstName.get();}公共 StringProperty firstNameProperty() {返回名字;}公共字符串 getLastName() {返回 lastName.get();}公共 StringProperty lastNameProperty() {返回姓氏;}}}

表格过滤从第一页开始,如果它溢出",则从第二页开始,依此类推.这是预期的结果吗?

附言我重构/简化了一点代码,比如用 lambdas 替换内部类并删除一些不必要的元素 + 将过滤扩展到姓氏,以获得更多的过滤可能性,但您可以根据需要使用它们.

I did some research on TableView's Filtering and Pagination separately.

Filtering : this post helped me as my need
Pagination : this, this post helped me also

I want to combine them together like so:

In Details --------------
I tried to make the pagination functionality first and it worked,
secondly, when i would start typing to the TextField filter functionality will match/filter the data from ObservableList, then rearrange the pagination according to the matched data size and show them through the table like the Datatable's search and pagination does and that's what i wanted, but i failed

My Code ...

PersonTableController.java

public class PersonTableController {

    @FXML private TextField filterField;
    @FXML private TableView<Person> personTable;
    @FXML private TableColumn<Person, Integer> slColumn;
    @FXML private TableColumn<Person, String> firstNameColumn;
    @FXML private TableColumn<Person, String> lastNameColumn;
    @FXML private Pagination pagination;
    private ObservableList<Person> masterData = FXCollections.observableArrayList();
    private int dataSize;
    private int rowsPerPage = 4;

    public PersonTableController() {
        masterData.add(new Person(1, "Hans", "Muster"));
        masterData.add(new Person(2, "Ruth", "Mueller"));
        masterData.add(new Person(3, "Heinz", "Kurz"));
        masterData.add(new Person(4, "Cornelia", "Meier"));
        masterData.add(new Person(5, "Cornelia", "Meier"));
        masterData.add(new Person(6, "Werner", "Meyer"));
        masterData.add(new Person(7, "Lydia", "Kunz"));
        masterData.add(new Person(8, "Anna", "Best"));
        masterData.add(new Person(9, "Stefan", "Meier"));
        masterData.add(new Person(10, "Hans", "Muster"));
        masterData.add(new Person(11, "Ruth", "Mueller"));
        masterData.add(new Person(12, "Heinz", "Kurz"));
        masterData.add(new Person(13, "Werner", "Meyer"));
        masterData.add(new Person(14, "Lydia", "Kunz"));
    }

    @FXML
    private void initialize() {

        dataSize = masterData.size();

        pagination.currentPageIndexProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                changeTableView(newValue.intValue(), rowsPerPage);
            }

        });

        FilteredList<Person> filteredData = new FilteredList<>(masterData, p -> true);

        filterField.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(person -> {
                if (newValue == null || newValue.isEmpty())
                    return true;
                String lowerCaseFilter = newValue.toLowerCase();

                if (person.getFirstName().toLowerCase().indexOf(lowerCaseFilter) != -1) {
                    return true; // Filter matches first name.
                }
                return false; // Does not match.
            });
        });

        SortedList<Person> sortedData = new SortedList<>(filteredData);
        sortedData.comparatorProperty().bind(personTable.comparatorProperty());
        // personTable.setItems(sortedData);

        slColumn.setCellValueFactory(new PropertyValueFactory<Person, Integer>("sl"));
        firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
        lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));


        int totalPage = (int) (Math.ceil(dataSize * 1.0 / rowsPerPage));
        pagination.setPageCount(totalPage);
        pagination.setCurrentPageIndex(0);
        changeTableView(0, rowsPerPage);

    }

    private void changeTableView(int index, int limit) {

        int fromIndex = index * limit;
        int toIndex = Math.min(fromIndex + limit, dataSize);

        List<Person> subListObs = masterData.subList(fromIndex, toIndex);
        ObservableList<Person> tmpObsToSetTableVal = FXCollections.observableArrayList();

        personTable.getItems().clear();
        personTable.setItems(null);

        for (Person t : subListObs) {
            tmpObsToSetTableVal.add(t);
        }

        personTable.setItems(tmpObsToSetTableVal);

    }

}

Person.java

public class Person {

    private final IntegerProperty sl;
    private final StringProperty firstName;
    private final StringProperty lastName;

    public Person(Integer sl, String firstName, String lastName) {
        this.sl = new SimpleIntegerProperty(sl);
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
    }

    public Integer getSl() {
        return sl.get();
    }

    public void setSl(Integer sl) {
        this.sl.set(sl);
    }

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

    public void setFirstName(String firstName) {
        this.firstName.set(firstName);
    }

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

    public void setLastName(String lastName) {
        this.lastName.set(lastName);
    }

}

Main.java

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Pagination and Filtering");        
        try {
            FXMLLoader loader = new FXMLLoader(Main.class.getResource("PersonTable.fxml"));
            AnchorPane page = (AnchorPane) loader.load();
            Scene scene = new Scene(page);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

PersonTable.fxml

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>

<AnchorPane minWidth="315.0" prefHeight="400.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="PersonTableController">
  <children>
    <HBox id="HBox" alignment="CENTER" spacing="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
      <children>
        <Label text="Filter Table:" />
        <TextField fx:id="filterField" prefWidth="-1.0" HBox.hgrow="ALWAYS" />
      </children>
    </HBox>
    <TableView fx:id="personTable" prefHeight="-1.0" prefWidth="-1.0" tableMenuButtonVisible="false" AnchorPane.bottomAnchor="60.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="40.0">
      <columns>
            <TableColumn fx:id="slColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="SL" />
        <TableColumn fx:id="firstNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="First Name" />
        <TableColumn fx:id="lastNameColumn" maxWidth="5000.0" minWidth="10.0" prefWidth="120.0" text="Last Name" />
      </columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
    </TableView>
      <HBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
         <children>
            <Pagination fx:id="pagination" />
         </children>
      </HBox>
  </children>
</AnchorPane>

any help :) plz

解决方案

here is my simple solution to your problem:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {

    @FXML
    private TextField filterField;
    @FXML
    private TableView<Person> personTable;
    @FXML
    private TableColumn<Person, Integer> slColumn;
    @FXML
    private TableColumn<Person, String> firstNameColumn;
    @FXML
    private TableColumn<Person, String> lastNameColumn;
    @FXML
    private Pagination pagination;

    private static final int ROWS_PER_PAGE = 4;
    private ObservableList<Person> masterData = FXCollections.observableArrayList();
    private FilteredList<Person> filteredData;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        setupData();
        filteredData = new FilteredList<>(masterData, p -> true);
        filterField.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(
                    person -> newValue == null || newValue.isEmpty() || person.getFirstName().toLowerCase()
                            .contains(newValue.toLowerCase()) || person.getLastName().toLowerCase()
                            .contains(newValue.toLowerCase()));
            changeTableView(pagination.getCurrentPageIndex(), ROWS_PER_PAGE);
        });

        slColumn.setCellValueFactory(data -> data.getValue().slProperty().asObject());
        firstNameColumn.setCellValueFactory(data -> data.getValue().firstNameProperty());
        lastNameColumn.setCellValueFactory(data -> data.getValue().lastNameProperty());

        int totalPage = (int) (Math.ceil(masterData.size() * 1.0 / ROWS_PER_PAGE));
        pagination.setPageCount(totalPage);
        pagination.setCurrentPageIndex(0);
        changeTableView(0, ROWS_PER_PAGE);
        pagination.currentPageIndexProperty().addListener(
                (observable, oldValue, newValue) -> changeTableView(newValue.intValue(), ROWS_PER_PAGE));
    }

    public void setupData() {
        masterData.add(new Person(1, "Hans", "Muster"));
        masterData.add(new Person(2, "Ruth", "Mueller"));
        masterData.add(new Person(3, "Heinz", "Kurz"));
        masterData.add(new Person(4, "Cornelia", "Meier"));
        masterData.add(new Person(5, "Cornelia", "Meier"));
        masterData.add(new Person(6, "Werner", "Meyer"));
        masterData.add(new Person(7, "Lydia", "Kunz"));
        masterData.add(new Person(8, "Anna", "Best"));
        masterData.add(new Person(9, "Stefan", "Meier"));
        masterData.add(new Person(10, "Hans", "Muster"));
        masterData.add(new Person(11, "Ruth", "Mueller"));
        masterData.add(new Person(12, "Heinz", "Kurz"));
        masterData.add(new Person(13, "Werner", "Meyer"));
        masterData.add(new Person(14, "Lydia", "Kunz"));
    }

    private void changeTableView(int index, int limit) {

        int fromIndex = index * limit;
        int toIndex = Math.min(fromIndex + limit, masterData.size());

        int minIndex = Math.min(toIndex, filteredData.size());
        SortedList<Person> sortedData = new SortedList<>(
                FXCollections.observableArrayList(filteredData.subList(Math.min(fromIndex, minIndex), minIndex)));
        sortedData.comparatorProperty().bind(personTable.comparatorProperty());

        personTable.setItems(sortedData);

    }

    class Person {

        private final IntegerProperty sl;
        private final StringProperty firstName;
        private final StringProperty lastName;

        public Person(Integer sl, String firstName, String lastName) {
            this.sl = new SimpleIntegerProperty(sl);
            this.firstName = new SimpleStringProperty(firstName);
            this.lastName = new SimpleStringProperty(lastName);
        }

        public int getSl() {
            return sl.get();
        }

        public IntegerProperty slProperty() {
            return sl;
        }

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

        public StringProperty firstNameProperty() {
            return firstName;
        }

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

        public StringProperty lastNameProperty() {
            return lastName;
        }
    }
}

The table filtering begins on the first page, and if it "overflows" then on the second and so on. This is the expected result?

P.S. I refactored/simplified a little bit the code, like replace the inner classes with lambdas and removed a few unnecessary element + extended the filtering to last name, to get a larger amount of filter possibility, but you can use them as you want.

这篇关于带分页的 JavaFX TableView 过滤(一起)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆