Javafx 子项溢出 FlowPane

标签 java user-interface javafx fxml

我正在重做project我用processing做的因为我想在 JavaFX 中进行一些练习,因为我明年在大学里需要它,它会给我比处理更多的 ui 自由。这意味着我是用 javafx 做事的新手,抱歉。

我试图在我的主窗口中有一个容器来容纳一些 Pane 。稍后我将在这些 Pane 上单独进行绘制。我选择了 FlowPane,较小的 Pane 只是 Pane 。我希望如果窗口的大小发生变化,则会创建(删除)更多 Pane ,以便在容器上始终可见完美数量的 Pane (这有点难以解释,但请查看链接的图片下面,您就会明白)。这在 99% 的时间里都工作得很好,但有时 Pane 会溢出流程 Pane 。我尝试了很多方法来解决这个问题(几乎是暴力破解,哈哈),但我无法得到比这更好的结果。

不良行为

enter image description here

期望的行为

enter image description here

Github如果您想亲自尝试一下该项目

Controller 代码:

public class MainWindowController {

    private int sizeOfOneGame = 100; //In pixel

    //Space between the frame of the Pane that holds all games and the games
    private int[] paddingAroundGames = {30, 30, 30, 30}; //Top, Right, Bottom, Left

    //Space between two games
    private int[] gapBetweenGames = {10, 10}; //X, Y

    @FXML
    FlowPane flowPaneGames;

    public void initialize(){

        //Sets space between two games in the flowPane
        flowPaneGames.setHgap(gapBetweenGames[0]);
        flowPaneGames.setVgap(gapBetweenGames[1]);

        //Sets space between all games and the border of the flowPane
        flowPaneGames.setPadding(new Insets(paddingAroundGames[0], paddingAroundGames[1], paddingAroundGames[2], paddingAroundGames[3]));

        //Draws one frame around the flowPane
        flowPaneGames.setStyle("-fx-border-color: black");

        //Aligns the panes to the center
        flowPaneGames.setAlignment(Pos.BASELINE_CENTER);

        //Adds listeners to the width and height of the flowPane holding the games -> Adjusts shown Panes on size change
        flowPaneGames.widthProperty().addListener(e -> flowPaneGamesSizeChanged());
        flowPaneGames.heightProperty().addListener(e -> flowPaneGamesSizeChanged());

    }

    private void flowPaneGamesSizeChanged(){

        //TODO: Sometimes some panes are bigger than the flowPane

        //Available space for games x and y
        int totalSpaceX = (int) (flowPaneGames.getWidth() - paddingAroundGames[1] - paddingAroundGames[3] + gapBetweenGames[0]);
        int totalSpaceY = (int) (flowPaneGames.getHeight() - paddingAroundGames[0] - paddingAroundGames[2] + gapBetweenGames[1]);

        int totatlSizeOfOneGameX = sizeOfOneGame + gapBetweenGames[0];
        int totatlSizeOfOneGameY = sizeOfOneGame + gapBetweenGames[1];

        int totalSpaceForGamesX = (int) (((double) totalSpaceX) / ((double) totatlSizeOfOneGameX));
        int totalSpaceForGamesY = (int) (((double) totalSpaceY) / ((double) totatlSizeOfOneGameY));

        //Total amount of games
        int totalSpaceForGames = totalSpaceForGamesX * totalSpaceForGamesY;

        System.out.println("Width: " + flowPaneGames.getWidth());
        System.out.println("Height: " + flowPaneGames.getHeight());

        //We have more games shown that there should be we remove the last ones
        while (flowPaneGames.getChildren().size() > totalSpaceForGames) {

            //We remove the last game
            flowPaneGames.getChildren().remove(flowPaneGames.getChildren().size() - 1);
        }

        //While we have less games shown that there should be we add new ones
        while (flowPaneGames.getChildren().size() < totalSpaceForGames) {

            flowPaneGames.getChildren().add(generateNewPane());

        }
    }

    private Pane generateNewPane(){

        //Generates a new pane and returns it
        Pane pane = new Pane();
        pane.setPrefSize(sizeOfOneGame, sizeOfOneGame);
        pane.setStyle("-fx-border-color: black");

        return pane;
    }
}

如果有人能帮助我解决这个问题,我会非常高兴,因为(即使它只在少数情况下发生)它确实困扰着我。

旁注:我已经在这里问过这个问题,但我在这个问题上几乎没有付出努力,几乎没有得到任何答案,这次我试图做得更好。 Ppl 还提示我没有真正遵循 java 的命名约定,我尝试倾听并希望代码现在更容易阅读。

最佳答案

问题的原因是没有考虑到容器的边框宽度。要考虑容器的边框宽度,totalSpaceXtotalSpaceY必须按如下方式确定:

int totalSpaceX = (int) (flowPaneGames.getWidth() - paddingAroundGames[1] - paddingAroundGames[3] + gapBetweenGames[0] - flowPaneGames.getBorder().getStrokes().get(0).getWidths().getLeft() - flowPaneGames.getBorder().getStrokes().get(0).getWidths().getRight());
int totalSpaceY = (int) (flowPaneGames.getHeight() - paddingAroundGames[0] - paddingAroundGames[2] + gapBetweenGames[1] - flowPaneGames.getBorder().getStrokes().get(0).getWidths().getTop() - flowPaneGames.getBorder().getStrokes().get(0).getWidths().getBottom());

左图显示容器高度和宽度为492每个,都考虑到容器的边框宽度。容器的边框宽度为1默认情况下。恰好 4 个子 Pane 适合宽度:492 = 2 x border width of container (= 1) + 2 * padding (= 30) + 3 * gap (= 10) + 4 * child pane width (= 100) 。这同样适用于高度。

如果宽度和/或高度减少 1 , 1每个子 Pane 的宽度和/或高度都被省略。中图显示容器高度和宽度为 491每个都考虑了容器的边框宽度。

如果不考虑容器的边框宽度,则假定的空间比实际可用的空间多,并且会创建过多的子 Pane 。右图显示容器高度和宽度为 491每个没有考虑边框宽度(即它显示当前代码的作用)。

enter image description here

编辑:

根据@Slaw的建议,totalSpaceXtotalSpaceY可以使用 Region#snappedXXXInset() 更轻松地计算:

int totalSpaceX = (int) (flowPaneGames.getWidth() - flowPaneGames.snappedLeftInset() - flowPaneGames.snappedRightInset() + gapBetweenGames[0]);
int totalSpaceY = (int) (flowPaneGames.getHeight() - flowPaneGames.snappedTopInset() - flowPaneGames.snappedBottomInset() + gapBetweenGames[1]);

还有 snapToPixel 应该设置(这是默认值)。

关于Javafx 子项溢出 FlowPane,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57026230/

相关文章:

ios - iOS 如何将 UI 对象连接到 View Controller 对象

ios - 根据用户登录与否管理 iOS 应用程序 UI 状态

.net - 快速 .NET WPF/WinForms 应用程序的示例?

JavaFX 警报信息不再显示 ContentText 不知道为什么

java - Hibernate 创建了太多的 java 类

java - Spring中使用密码编码时用户登录失败

spring - 如何通过 Spring 发送电子邮件

java - 我怎样才能知道 Node 或 ButtonBase 是 Button?

java - synchronized 会自动标记变量 volatile 吗?

java - 我的回文检查器对某些不起作用,但对另一些却起作用? (JAVA)