首页 > 解决方案 > 在 Javafx 中,如何将网格窗格的大小单元格设置为父窗格的一小部分?

问题描述

我尝试在 JavaFx 中创建一个带有圆圈的 gridPane。我希望 gridPane 单元格使用 gridPane 中的所有可用空间。(GridPane 位于 BorderPane 的中心)但单元格不断调整大小以适应内部对象。如何让单元格使用所有可用空间?(以及如何将圆的半径设置为 BorderPane 中心可用空间的一小部分。

我对 JavaFx 很陌生,但我尝试使用 Columnconstraints 和 RowConstraints 来满足我的需要。它没有用。我还尝试在 GridPane 中绑定对象的大小以使用舞台大小的一小部分,但它无法正常工作,因为它与 BorderPane 中的平面不对应。

public void start(Stage primaryStage) throws Exception{
        BorderPane applicationLayout = new BorderPane();
        primaryStage.setTitle("Multi-level feedback simulator");
        Scene scene = new Scene(applicationLayout, 600, 600);
        primaryStage.setScene(scene);

        //Add the menu Bar
        //MainMenuBar menuBar = new MainMenuBar(primaryStage);
        //applicationLayout.setTop(menuBar);

        //Add the main zone of drawing
        TreeDrawingZone treeDrawingZone = new TreeDrawingZone(primaryStage,applicationLayout,3,3);

        applicationLayout.setCenter(treeDrawingZone);
        primaryStage.show();
        primaryStage.setMaximized(true);

    }

带有约束的 GridPane 代码。构造函数的最大部分创建了线条和圆圈来显示一棵树。绘图函数是 createLine() 和 createCircle()

 public class TreeDrawingZone extends Parent {
    private GridPane drawingZoneLayout;
    private Stage stage;
    private int columnNumber;
    private int rowNumber;
    private Pane rootPane;
    private List<Pair<Integer,Integer>> circlePositions;

    public TreeDrawingZone(Stage stage,Pane rootPane, int treeHeight, int childrenPerNode){
        this.stage = stage;
        drawingZoneLayout = new GridPane();
        columnNumber = 2*(int)Math.pow(childrenPerNode,treeHeight-1)-1;
        rowNumber = 2*treeHeight-1;
        circlePositions = new ArrayList<>();
        this.rootPane = rootPane;
        //TODO Use the correct height of the borderLayout (maybe with a upper level layout)
        System.out.println(columnNumber);
        System.out.println(rowNumber);
        //column Constraints
        for(int i = 1 ; i <= columnNumber ; i++){
            ColumnConstraints columnConstraints = new ColumnConstraints();
            columnConstraints.setPercentWidth((double) 100/columnNumber);
            columnConstraints.setFillWidth(true);
            drawingZoneLayout.getColumnConstraints().add(columnConstraints);
        }

        //row Constraints
        for(int i = 1 ; i <= rowNumber ; i++){
            RowConstraints rowConstraints = new RowConstraints();
            rowConstraints.setPercentHeight((double) 100/rowNumber);
            rowConstraints.setFillHeight(true);
            drawingZoneLayout.getRowConstraints().add(rowConstraints);
        }

        //Tree Representation
        //Base Line
        List<Integer> circleLineRepartition = new ArrayList<>();
        for(int i = 0 ; i < columnNumber; i ++){
            if(i % 2 == 0){
                circleLineRepartition.add(i);
            }
        }
        System.out.println(circleLineRepartition);
        //Creation of the grid line per line
        for(int i = rowNumber-1 ; i >=0 ; i-=2){
            if(i % 2 == 0) {
                //Case of the line with circles
                for (Integer circlePosition : circleLineRepartition) {
                    Pane circlePane;
                    if (i == 0) {
                        circlePane = createCircle(true, false);
                    } else if (i == rowNumber - 1) {
                        circlePane = createCircle(false, true);
                    } else {
                        circlePane = createCircle();
                    }
                    drawingZoneLayout.add(circlePane, circlePosition, i);
                    circlePositions.add(new Pair<>(circlePosition, i));
                }
                List<Integer> upperCircleLineRepartition;
                //Create the lines
                //The following block enumerates the different cases to create the lines between the dotes
                try {
                    upperCircleLineRepartition = getoddlyRepartedCenters(childrenPerNode, circleLineRepartition);
                    if (i > 0) {
                        int minPosition = circleLineRepartition.get(0);
                        int maxPosition = circleLineRepartition.get(circleLineRepartition.size() - 1);
                        int position = 0;
                        boolean drawHorizontal = true;
                        int linkedNodeCount = 0;
                        for (int j = minPosition; j <= maxPosition; j++) {
                            Pane linesPane;
                            if (j == circleLineRepartition.get(position) && minPosition != maxPosition) {
                                //Update the number of linked Nodes
                                if(drawHorizontal) {
                                    linkedNodeCount += 1;
                                    if(linkedNodeCount == childrenPerNode)
                                        drawHorizontal = false;
                                }else{
                                    linkedNodeCount = 1;
                                    drawHorizontal = true;
                                }
                                //First element
                                if (linkedNodeCount == 1) {
                                    if(upperCircleLineRepartition.contains(j)){
                                        linesPane = createLines(LineDirection.NORTH,LineDirection.SOUTH,LineDirection.EAST);
                                    }else {
                                        linesPane = createLines(LineDirection.SOUTH, LineDirection.EAST);
                                    }
                                }
                                //Last element
                                else if (linkedNodeCount == childrenPerNode) {
                                    if(upperCircleLineRepartition.contains(j)){
                                        linesPane = createLines(LineDirection.NORTH,LineDirection.SOUTH,LineDirection.WEST);
                                    }else {
                                        linesPane = createLines(LineDirection.WEST, LineDirection.SOUTH);
                                    }
                                }//bridge with under and upper level
                                else if(upperCircleLineRepartition.contains(j)) {
                                    linesPane = createLines(LineDirection.SOUTH, LineDirection.NORTH, LineDirection.EAST, LineDirection.WEST);
                                }
                                //other children
                                else{
                                    linesPane = createLines(LineDirection.SOUTH, LineDirection.EAST, LineDirection.WEST);
                                }
                                position++;
                            }
                            //Only one child
                            else if (minPosition == maxPosition) {
                                linesPane = createLines(LineDirection.SOUTH, LineDirection.NORTH);
                            }
                            //Bridge between children
                            else {
                                if(drawHorizontal) {
                                    if (upperCircleLineRepartition.contains(j)) {
                                        linesPane = createLines(LineDirection.NORTH, LineDirection.EAST, LineDirection.WEST);
                                    } else {
                                        linesPane = createLines(LineDirection.WEST, LineDirection.EAST);
                                    }
                                }else{
                                    linesPane = createLines();
                                }
                            }

                            drawingZoneLayout.add(linesPane, j, i - 1);
                        }
                    }
                    circleLineRepartition = new ArrayList<>(upperCircleLineRepartition);
                } catch (Exception e) {
                    System.out.println("Invalid line given");
                }
            }
        }
         drawingZoneLayout.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
        //TODO remove GridLines after debug
        drawingZoneLayout.setGridLinesVisible(true);
        this.getChildren().add(drawingZoneLayout);
    }


    private Pane createCircle(){
        return createCircle(false,false);
    }

    private Pane createCircle(boolean isRoot, boolean isLeaf){
        Pane circlePane = new Pane();
        Circle circle = new Circle();
        circle.centerXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
        circle.centerYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
        circle.radiusProperty().bind(Bindings.min(stage.widthProperty().divide(columnNumber).divide(2),stage.heightProperty().divide(rowNumber).divide(2)));
        circlePane.getChildren().add(circle);
        if(!isLeaf) {
            circlePane.getChildren().add(createLines(LineDirection.SOUTH));
        }
        if(!isRoot){
            circlePane.getChildren().add(createLines(LineDirection.NORTH));
        }
        return circlePane;
    }

    private Pane createLines(LineDirection ... directions){
        Pane linesGroup = new Pane();
        for(LineDirection direction : directions){
            linesGroup.getChildren().add(createLine(direction));
        }
        return linesGroup;
    }

    private Line createLine(LineDirection direction){
        Line line = new Line();
        if(direction == LineDirection.EAST || direction == LineDirection.WEST){
            line.startYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
            line.endYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
            line.startXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
            if(direction == LineDirection.EAST){
                line.endXProperty().bind(stage.widthProperty().divide(columnNumber));
            }
            else{
                line.setEndX(0);
            }
        }
        else{
            line.startXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
            line.endXProperty().bind(stage.widthProperty().divide(columnNumber).divide(2));
            line.startYProperty().bind(stage.heightProperty().divide(rowNumber).divide(2));
            if(direction == LineDirection.NORTH){
                line.setEndY(0);
            }else{
                line.endYProperty().bind(stage.heightProperty().divide(rowNumber));
            }
        }
        line.setStrokeWidth(1);
        line.setFill(null);
        line.setStroke(Color.BLACK);
        return line;
    }

    private int getCenter(List<Integer> childrenNodesPosition) throws Exception {
        if (childrenNodesPosition.size() == 0){
            throw new Exception("Tried to get the center of an empty list");
        }else{
            int sum = 0;
            for(int childNodePosition : childrenNodesPosition){
                sum += childNodePosition;
            }
            return sum/childrenNodesPosition.size();
        }
    }

    private List<Integer> getoddlyRepartedCenters(int nodeNumberPerParent, List<Integer> childrenNodesPosition) throws Exception {
        int parentNumber = childrenNodesPosition.size()/nodeNumberPerParent;
        int nextPosition = 0;
        List<Integer> regularParentCenters = new ArrayList<>(parentNumber);
        for(int i = 0 ; i < parentNumber ; i++){
            regularParentCenters.add(getCenter(childrenNodesPosition.subList(nextPosition,nextPosition + nodeNumberPerParent)));
            nextPosition = nextPosition + nodeNumberPerParent;
        }
        return regularParentCenters;
    }

}


我要纠正的结果

标签: javafxgridpane

解决方案


推荐阅读