Javafx儿童溢出FlowPane

时间:2019-07-14 09:45:35

标签: java user-interface javafx fxml

我要重做一个project,因为我想在JavaFX上做一些练习,因为我明年要在uniuni上用它,这将给我带来更多的自由, ui比处理要好。抱歉,这意味着我不熟悉Javafx。

我试图在我的主窗口中容纳一个容纳一些窗格的容器。稍后,我将在这些窗格上分别进行绘制。我使用了FlowPane,较小的窗格就是窗格。我希望如果窗口的大小发生变化,那么就会创建(删除)更多的窗格,以便始终在容器上看到最合适的窗格数(这有点难以解释,但是请看一下链接的图片在下面,您将明白这个想法)。这在99%的时间内都可以正常工作,但是有时窗格溢出了窗格。我花了很多时间来解决这个问题(蛮横的,大声笑),但我没有比这更好的了。

不良行为

processing

期望的行为

enter image description here

enter image description here,如果您想自己尝试的话

控制器代码:

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的命名约定,我试着听一下,希望现在可以更好地阅读代码。

1 个答案:

答案 0 :(得分:1)

此问题的原因是未考虑容器的边框宽度。要考虑容器的边框宽度,必须按以下方式确定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个子窗格:492 = 2 x border width of container (= 1) + 2 * padding (= 30) + 3 * gap (= 10) + 4 * child pane width (= 100)。高度也一样。

如果宽度和/或高度减小了1,则1子窗格的宽度和/或高度均被省略。中间的图显示了491的容器高度和宽度,每个高度和宽度都考虑到了容器的边框宽度。

如果不考虑容器的边框宽度,那么将假定比实际可用空间更多的空间,并且会创建太多子窗格。右图显示了491的容器高度和宽度,每个都考虑了边框宽度(即,它显示了当前代码的作用)。

enter image description here

编辑:

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

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

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

相关问题