Javafx 儿童溢出 FlowPane
Javafx children overflowing FlowPane
我正在重做 project i did with processing,因为我想在 JavaFX 中进行一些练习,因为明年我将在 uni 中需要它,这将使我在 ui 方面比 ui 更自由加工确实如此。这意味着我刚开始使用 javafx,抱歉。
我正在尝试在我的主 window 中放置一个容器来容纳一些窗格。在这些窗格上,我稍后会单独使用。我选择了 FlowPane,较小的窗格只是,嗯,窗格。我希望如果 window 的大小发生变化,则会创建(删除)更多窗格,并且容器上始终可以看到完美数量的窗格(这有点难以解释,但请看一下在下面链接的图片中,您会明白的)。这在 99% 的时间里都能正常工作,但有时窗格会溢出流程窗格。我尝试了很多来解决这个问题(几乎是蛮力解决的,哈哈),但我找不到比这更好的了。
不良行为
期望的行为
Github项目的如果你想自己尝试
控制器代码:
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;
}
}
如果有人能帮我解决这个问题,我会很高兴(即使它只在少数情况下发生)它真的很困扰我。
旁注:我已经在这里问过这个问题,但我几乎没有努力解决这个问题,结果几乎没有任何答案,这次我试着做得更好。人们还抱怨我没有真正遵循 java 的命名约定,我试着听听并希望代码现在更好读。
问题的原因是没有考虑到容器的边框宽度。考虑到容器的边框宽度,totalSpaceX
和 totalSpaceY
必须确定如下:
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 个子窗格适合宽度:492 = 2 x border width of container (= 1) + 2 * padding (= 30) + 3 * gap (= 10) + 4 * child pane width (= 100)
。高度也是如此。
如果宽度 and/or 高度减少 1
,1
子窗格的宽度 and/or 高度将被省略。中间的图显示了容器的高度和宽度 491
,每个都考虑了容器的边框宽度。
在不考虑容器边框宽度的情况下,假设 space 比实际可用的多,并且创建了太多的子窗格。右图显示了容器高度和宽度 491
每个 没有 考虑边框宽度(即它显示了当前代码的作用)。
编辑:
根据@Slaw 的建议,使用 Region#snappedXXXInset()
:
可以更轻松地计算 totalSpaceX
和 totalSpaceY
int totalSpaceX = (int) (flowPaneGames.getWidth() - flowPaneGames.snappedLeftInset() - flowPaneGames.snappedRightInset() + gapBetweenGames[0]);
int totalSpaceY = (int) (flowPaneGames.getHeight() - flowPaneGames.snappedTopInset() - flowPaneGames.snappedBottomInset() + gapBetweenGames[1]);
还应设置 snapToPixel
(默认设置)。
我正在重做 project i did with processing,因为我想在 JavaFX 中进行一些练习,因为明年我将在 uni 中需要它,这将使我在 ui 方面比 ui 更自由加工确实如此。这意味着我刚开始使用 javafx,抱歉。
我正在尝试在我的主 window 中放置一个容器来容纳一些窗格。在这些窗格上,我稍后会单独使用。我选择了 FlowPane,较小的窗格只是,嗯,窗格。我希望如果 window 的大小发生变化,则会创建(删除)更多窗格,并且容器上始终可以看到完美数量的窗格(这有点难以解释,但请看一下在下面链接的图片中,您会明白的)。这在 99% 的时间里都能正常工作,但有时窗格会溢出流程窗格。我尝试了很多来解决这个问题(几乎是蛮力解决的,哈哈),但我找不到比这更好的了。
不良行为
期望的行为
Github项目的如果你想自己尝试
控制器代码:
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;
}
}
如果有人能帮我解决这个问题,我会很高兴(即使它只在少数情况下发生)它真的很困扰我。
旁注:我已经在这里问过这个问题,但我几乎没有努力解决这个问题,结果几乎没有任何答案,这次我试着做得更好。人们还抱怨我没有真正遵循 java 的命名约定,我试着听听并希望代码现在更好读。
问题的原因是没有考虑到容器的边框宽度。考虑到容器的边框宽度,totalSpaceX
和 totalSpaceY
必须确定如下:
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 个子窗格适合宽度:492 = 2 x border width of container (= 1) + 2 * padding (= 30) + 3 * gap (= 10) + 4 * child pane width (= 100)
。高度也是如此。
如果宽度 and/or 高度减少 1
,1
子窗格的宽度 and/or 高度将被省略。中间的图显示了容器的高度和宽度 491
,每个都考虑了容器的边框宽度。
在不考虑容器边框宽度的情况下,假设 space 比实际可用的多,并且创建了太多的子窗格。右图显示了容器高度和宽度 491
每个 没有 考虑边框宽度(即它显示了当前代码的作用)。
编辑:
根据@Slaw 的建议,使用 Region#snappedXXXInset()
:
totalSpaceX
和 totalSpaceY
int totalSpaceX = (int) (flowPaneGames.getWidth() - flowPaneGames.snappedLeftInset() - flowPaneGames.snappedRightInset() + gapBetweenGames[0]);
int totalSpaceY = (int) (flowPaneGames.getHeight() - flowPaneGames.snappedTopInset() - flowPaneGames.snappedBottomInset() + gapBetweenGames[1]);
还应设置 snapToPixel
(默认设置)。