我要重做一个project,因为我想在JavaFX上做一些练习,因为我明年要在uniuni上用它,这将给我带来更多的自由, ui比处理要好。抱歉,这意味着我不熟悉Javafx。
我试图在我的主窗口中容纳一个容纳一些窗格的容器。稍后,我将在这些窗格上分别进行绘制。我使用了FlowPane,较小的窗格就是窗格。我希望如果窗口的大小发生变化,那么就会创建(删除)更多的窗格,以便始终在容器上看到最合适的窗格数(这有点难以解释,但是请看一下链接的图片在下面,您将明白这个想法)。这在99%的时间内都可以正常工作,但是有时窗格溢出了窗格。我花了很多时间来解决这个问题(蛮横的,大声笑),但我没有比这更好的了。
不良行为
期望的行为
控制器代码:
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的命名约定,我试着听一下,希望现在可以更好地阅读代码。
答案 0 :(得分:1)
此问题的原因是未考虑容器的边框宽度。要考虑容器的边框宽度,必须按以下方式确定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)
。高度也一样。
如果宽度和/或高度减小了1
,则1
子窗格的宽度和/或高度均被省略。中间的图显示了491
的容器高度和宽度,每个高度和宽度都考虑到了容器的边框宽度。
如果不考虑容器的边框宽度,那么将假定比实际可用空间更多的空间,并且会创建太多子窗格。右图显示了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
(这是默认设置)。