【问题标题】:JavaFX TableView Filtering with Pagination (Together)JavaFX TableView 过滤与分页(一起)
【发布时间】:2018-08-06 02:38:28
【问题描述】:

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

过滤: this 帖子根据我的需要帮助了我
分页: thisthis 帖子也帮助了我

我想像这样将它们组合在一起:

详细说明 --------------
我尝试先创建分页功能并且它起作用了,
其次,当我开始输入TextField 时,过滤器功能将匹配/过滤来自ObservableList 的数据,然后根据匹配的数据大小重新排列分页并通过表格显示它们,如Datatable 的搜索和分页确实是我想要的,但我失败了

我的代码...

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>

任何帮助:) plz

【问题讨论】:

    标签: javafx pagination filtering


    【解决方案1】:

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

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

    表格过滤从第一页开始,如果“溢出”则在第二页开始,以此类推。这是预期的结果?

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

    【讨论】:

    • 感谢您的努力。快完成了!我想根据过滤器值重新排列分页,但您的代码仍然可以正常工作。我刚刚在.setPredicate 之后添加了这个pagination.setPageCount((int) (Math.ceil(filteredData.size() * 1.0 / ROWS_PER_PAGE))); 行,现在它完成了
    • 是的,有道理,我忘了。
    • 1 只针对@Sunflame 的问题:: 我的问题是否提供了太多信息(用于自我纠正)???顺便谢谢...
    • 我明白你想要做什么/实现什么,我只是问这是否是预期的结果,因为我忘记了你在第一条评论中提到的,我想如果你去第四页怎么办并过滤表格,即使表格中的文本匹配,数据也会消失。但现在将页面数量减少到所需数量更有意义。
    • 我真的不知道你为什么在这个问题上得到-2,因为我也花了一点力气才得到正确答案。可能我没有看到最初的问题,你也没有像现在这样清楚地问,或者代码丢失了。除了努力,我认为它可以在很多地方使用。
    猜你喜欢
    • 2018-11-18
    • 2013-02-27
    • 2020-06-30
    • 2017-04-20
    • 1970-01-01
    • 2021-12-29
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多