Reputation: 15
I made an FXML in the Scenebuilder with a Tableview and Pagination. But I am having trouble to get the pagination to work, especially the PageFactory.
I have following code:
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?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?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
Controller:
public void fillTable(int page) {
this.dataModel.setTracksPage(page);
this.table.setItems(FXCollections.observableArrayList(this.dataModel.getTracks().getData()));
this.paginator.setCurrentPageIndex(page);
}
@Override
public void showOverview() {
recordsOverview.setVisible(true);
}
@Override
public void setDataModel(DataModel dataModel) {
if (this.dataModel == null) {
this.dataModel = dataModel;
}
fillTable(1);
paginator.setPageCount(this.dataModel.getTracks().getTotalPages());
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return null; // ???
}
);
}
I just want to fill the table with new data, but returning null gives me errors. If I return something else like return new BorderPane(table), It doesn't work either, same error. How can I solve this issue?
Upvotes: 1
Views: 584
Reputation: 209684
Your page factory needs to return the node that will be displayed as the "page". The Pagination
will then manage that node and make it part of the scene graph under it. What you want to do is display the TableView
in the pagination, so you should return it from the page factory.
You didn't post any of the stack traces from the errors you mention, but I'm guessing that what's happening is that when you return the table, you get an error because the TableView
is already part of the scene graph, and nodes can't exist in two different places.
One solution is to omit the table entirely from the FXML, and just define it in the controller (set it up in the initialize()
method, then return the reference to it from the page factory).
If you still want it defined in the FXML file, you can define elements in FXML which are not part of the scene graph by wrapping them in a <fx:define>
block.
So your FXML would look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?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?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<fx:define>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</fx:define>
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
and then you do
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return table;
}
);
Upvotes: 3