JavaFX 分页 : setPageCount(int) calls the page factory again but does not show the page

标签 java javafx pagination javafx-8

前置故事:

好吧,我在自定义分页控件方面遇到了另一个问题,我想我已经弄清楚为什么它不能按预期工作。然而它仍然没有起作用。因此,我创建了一个最小示例来找出发生了什么以及我的代码中是否有其他内容搞砸了。

问题

设置页数时,再次调用页面工厂,但不显示正在返回的页面。我就是不明白为什么。

<小时/>

代码示例的附加信息:

如果注释掉 setPageCount(4),将加载“初始页面”。但是,当您不将其注释掉时,只有切换页面或调整大小时,一切才会起作用。

编辑:我还想知道如果我的当前页面低于新页面计数,为什么会调用页面工厂。看起来很奇怪 - 如果我的新页面计数低于当前页面索引,除了将当前页面索引更改为 0 之外,它不应该只调用页面工厂吗?

<小时/>

代码 - 最小工作示例

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main  extends Application{

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

    @Override
    public void start(Stage primaryStage) throws Exception {

        StackPane root = new StackPane();
        Pagination pagination = new Pagination();

        pagination.setPageFactory( index -> {
            TilePane tilePane = new TilePane();
            System.out.println("Trace: start: createTilePane");
            System.out.println("TilePane: " + tilePane);

            tilePane.widthProperty().addListener( observable -> {
                System.out.println("WidthProperty-Listener");
                System.out.println("tilePane: w: " + tilePane.getWidth() + "; h: " + tilePane.getHeight());
            });
            tilePane.heightProperty().addListener( observable -> {
                System.out.println("HeightProperty-Listener");
                System.out.println("tilePane: w: " + tilePane.getWidth() + "; h: " + tilePane.getHeight());
                pagination.setPageCount(4);
            });
            tilePane.setOnMouseClicked( event -> {
                System.out.println("Trace: onMouseClicked()");
                System.out.println("tilePane: " + tilePane);
            });
            tilePane.setBackground(new Background(new BackgroundFill(Color.BEIGE, null, null)));


            System.out.println("Trace: end: createTilePane");
            return tilePane;
        });

        root.getChildren().add(pagination);

        Scene scene = new Scene(root, 500, 500);

        primaryStage.setScene(scene);
        primaryStage.show();

    }
}

最佳答案

你可以这样做。我使用旋转器在演示中更加灵活:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Pagination;
import javafx.scene.control.Spinner;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TilesOnAGrid extends Application {

    Pagination pagination = new Pagination();

    Spinner<Integer> totalSpinner = new Spinner<Integer>(0, 30, 12);
    Spinner<Integer> rowSpinner = new Spinner<Integer>(1, 5, 2);
    Spinner<Integer> colSpinner = new Spinner<Integer>(1, 5, 2);

    @Override
    public void start(Stage primaryStage) throws Exception {

        BorderPane root = new BorderPane();

        pagination.setPageFactory(new Callback<Integer, Node>() {
            @Override
            public Node call(Integer index) {

                StackPane page = new StackPane();

                GridPane grid = new GridPane();

                grid.setHgap(10);
                grid.setVgap(10);
                grid.setPadding(new Insets(0, 10, 0, 10));

                int total = totalSpinner.getValue();
                int rows = rowSpinner.getValue();
                int cols = colSpinner.getValue();

                int offset = rows * cols * index;

                for (int row = 0; row < rows; row++) {
                    for (int col = 0; col < cols; col++) {

                        offset++;

                        if (offset > total)
                            break;

                        StackPane container = new StackPane();
                        container.setStyle("-fx-background-color:lightgrey");

                        Label label = new Label("Item Nr. " + offset);
                        container.getChildren().add(label);

                        GridPane.setRowIndex(container, row);
                        GridPane.setColumnIndex(container, col);
                        GridPane.setHgrow(container, Priority.ALWAYS);
                        GridPane.setVgrow(container, Priority.ALWAYS);

                        grid.getChildren().add(container);
                    }
                }

                page.getChildren().add(grid);

                return page;
            }
        });

        totalSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        rowSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        colSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());

        HBox toolbar = new HBox();
        toolbar.setPadding(new Insets(5,5,5,5));
        toolbar.setSpacing(5);
        toolbar.getChildren().addAll(new Label("Total"), totalSpinner, new Label("Columns"), colSpinner, new Label("Rows"), rowSpinner);

        root.setTop(toolbar);
        root.setCenter(pagination);

        Scene scene = new Scene(root, 800, 600);

        primaryStage.setScene(scene);
        primaryStage.show();

        layoutItems();

    }

    private void layoutItems() {

        int total = totalSpinner.getValue();
        int rows = rowSpinner.getValue();
        int cols = colSpinner.getValue();

        int pages = (int) Math.ceil(total / (double) (rows * cols));

        pagination.setPageCount(pages);
    }

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

enter image description here

关于您的代码,您不应更改工厂中的页数。如果您需要根据宽度/高度进行更改,您可以向根添加监听器

root.heightProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
root.widthProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());

或者无论您的分页容器是什么,并相应地计算行/列。

<小时/>

编辑

这是一个示例,当您单击“使用调整大小”复选框时,会考虑单元格的宽度和高度,即。 e.在调整父级大小时控制分页。更改行/列现在也应该可以工作。我正在发送自定义事件来触发更新。

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Pagination;
import javafx.scene.control.Spinner;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TilesOnAGrid extends Application {

    StackPane currentPageContainer = null;

    Pagination pagination = new Pagination();

    double minColWidth = 300;
    double minRowHeight = 300;

    Spinner<Integer> totalSpinner = new Spinner<Integer>(0, 30, 12);
    Spinner<Integer> rowSpinner = new Spinner<Integer>(1, 5, 2);
    Spinner<Integer> colSpinner = new Spinner<Integer>(1, 5, 2);

    BorderPane root;

    CheckBox useResizeCheckBox;

    @Override
    public void start(Stage primaryStage) throws Exception {

        root = new BorderPane();

        pagination.setPageFactory(new Callback<Integer, Node>() {
            @Override
            public Node call(Integer index) {

                currentPageContainer = createPage(index);
                currentPageContainer.addEventHandler(MyEvent.UPDATE, new MyEventHandler());

                return currentPageContainer;

            }
        });

        root.heightProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        root.widthProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        pagination.currentPageIndexProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        pagination.pageCountProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());

        totalSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        rowSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());
        colSpinner.valueProperty().addListener((ChangeListener<Number>) (observable, oldValue, newValue) -> layoutItems());

        Label totalLabel = new Label("Total");
        Label rowsLabel = new Label("Rows");
        Label columnsLabel = new Label("Columns");

        useResizeCheckBox = new CheckBox("Use Resizing");
        useResizeCheckBox.selectedProperty().addListener((ChangeListener<Boolean>) (observable, oldValue, newValue) -> {

            rowSpinner.setVisible(!newValue);
            colSpinner.setVisible(!newValue);
            rowsLabel.setVisible(!newValue);
            columnsLabel.setVisible(!newValue);

            layoutItems();

        });

        HBox toolbar = new HBox();
        toolbar.setPadding(new Insets(5, 5, 5, 5));
        toolbar.setSpacing(5);
        toolbar.getChildren().addAll(useResizeCheckBox, totalLabel, totalSpinner, columnsLabel, colSpinner, rowsLabel, rowSpinner);

        root.setTop(toolbar);
        root.setCenter(pagination);

        Scene scene = new Scene(root, 800, 800);

        primaryStage.setScene(scene);
        primaryStage.show();

        layoutItems();

    }

    public int getRows() {

        if (useResizeCheckBox.isSelected()) {
            return (int) Math.ceil(root.getBoundsInParent().getHeight() / minRowHeight);
        } else {
            return rowSpinner.getValue();
        }

    }

    public int getCols() {

        if (useResizeCheckBox.isSelected()) {
            return (int) Math.ceil(root.getBoundsInParent().getWidth() / minColWidth);
        } else {
            return colSpinner.getValue();
        }

    }

    private void layoutItems() {

        int total = totalSpinner.getValue();
        int rows = getRows();
        int cols = getCols();

        int pages = (int) Math.ceil(total / (double) (rows * cols));

        pagination.setPageCount(pages);

        if (currentPageContainer != null) {
            MyEvent myEvent = new MyEvent(pagination.getCurrentPageIndex());
            currentPageContainer.fireEvent(myEvent);
        }
    }

    public StackPane createPage(Integer index) {

        StackPane page = new StackPane();

        page.getChildren().setAll(getGrid(index));

        return page;
    }

    public GridPane getGrid(Integer index) {

        GridPane grid = new GridPane();

        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(0, 10, 0, 10));

        int total = totalSpinner.getValue();
        int rows = getRows();
        int cols = getCols();

        int offset = rows * cols * index;

        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {

                offset++;

                StackPane container = new StackPane();

                Label label;
                if (offset <= total) {

                    container.setStyle("-fx-background-color:lightgrey");
                    label = new Label("Item Nr. " + offset);

                } else {

                    label = new Label("");

                }

                container.getChildren().add(label);

                GridPane.setRowIndex(container, row);
                GridPane.setColumnIndex(container, col);
                GridPane.setHgrow(container, Priority.ALWAYS);
                GridPane.setVgrow(container, Priority.ALWAYS);

                grid.getChildren().add(container);
            }
        }

        return grid;
    }

    static class MyEvent extends Event {

        public static final EventType<MyEvent> UPDATE = new EventType<>(Event.ANY, "UPDATE");

        int index = 1;

        public MyEvent(int index) {
            super(UPDATE);
            this.index = index;
        }

        public int getIndex() {
            return index;
        }

    }

    private class MyEventHandler implements EventHandler<MyEvent> {
        @Override
        public void handle(MyEvent event) {

            currentPageContainer.getChildren().setAll(getGrid(event.getIndex()));

        }
    }

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

关于JavaFX 分页 : setPageCount(int) calls the page factory again but does not show the page,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36189228/

相关文章:

java - 使用接受任何类作为参数的方法创建 Java 接口(interface)

java - globalBinding 标签可以包含在根元素中吗?

java - 更改 TableView 中的表列背景,同时保留交替的行颜色?

android - 如何用kotlin实现分页

php - 使用分页过滤REDIS中的在线用户

java - 编译器在收集器 toMap 中给出一般错误

java - 如何在 HandlerInterceptorAdapter 中添加 HttpServletRequest header ?

java - 如何在 JavaFX 中递归添加菜单和子菜单?

css - 如何将css转换为bss

php - 查询结果的分页无法正常工作