带分页的 JavaFX TableView 过滤(一起) [英] JavaFX TableView Filtering with Pagination (Together)
问题描述
我分别对TableView的Filtering
和Pagination
做了一些研究.
过滤:
在细节中--------------
我尝试先实现分页功能,结果奏效了,
其次,当我开始输入 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 extends Number> 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屋!