0
votes

Scenario : A Stage contains a Scene.The Scene contains a StackPane. The height and width of the StackPane and Scene are bind together. The StackPane contains a Shape which is a union of Rectangle and Shape.

Issue - I am facing issue while binding a Shape class to the height of StackPane. How to bind a particular part of Shape class or the complete Shape class in my example?

Requirement - I have 2 requirements.

  1. When I maximize the stage, the StackPane gets increased since the height and width are bind to Scene but the Shape doesnt increase. I need both the Shape's(smallShape and bigRectangle) to increase in terms of height only.
  2. When I maximize the stage the StackPane should increase as well as only the bigger rectangle height should increase but not the other small rectangle i.e bigRectangle height should increase only.

Below is my code snippet

package application;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class BindingShape extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        StackPane stackPane = new StackPane();
        stackPane.setPrefHeight(200);
        stackPane.setPrefWidth(200);
        stackPane.setStyle("-fx-background-color: BEIGE");
        Shape smallShape = RectangleBuilder.create()
                .x(0)
                .y(3)
                .arcWidth(6)
                .arcHeight(6)
                .width(50) // allow overlap for union of tab and content rectangle
                .height(50)
                .build();

        Rectangle bigRectangle = RectangleBuilder.create()
                .x(25)
                .y(0)
                .arcWidth(10)
                .arcHeight(10)
                .width(100)
                .height(100)
                .build();
        Shape unionShape = Shape.union(smallShape, bigRectangle);
        unionShape.setFill(Color.rgb(0, 0, 0, .50));
        unionShape.setStroke(Color.BLUE);

        Group shapeGroup = new Group();
        shapeGroup.getChildren().add(unionShape);
        stackPane.getChildren().add(shapeGroup);

        Group paneGroup = new Group();
        paneGroup.getChildren().add(stackPane);

        Scene scene = new Scene(paneGroup, 400, 400,Color.LIGHTSKYBLUE);
        stackPane.prefHeightProperty().bind(scene.heightProperty().divide(2));
        stackPane.prefWidthProperty().bind(scene.widthProperty().divide(2));
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}

Please let me know the solution. Thanks in advance.

1
I use Java8 (1.8.0_11) with fx2, in that version, the RectangleBuilder is deprecated and Shape.union() does not exist... what version do you use? - Jens-Peter Haack
I am using Java8(1.8.0_25). Yes in this version RectangleBuilder is deprectaed but still we are able to sue it. If not RectangleBuilder I need to use directly Rectangle. But in that case also the problem will still persist. Please let me know if by dorectly using new Rectangle() the above requirements can be achieved. Shape.union does exist for me.The below link has it. docs.oracle.com/javafx/2/api/javafx/scene/shape/Shape.html - Anakar

1 Answers

1
votes

As the union cannot be resized in parts, I would rebuild the union if the container has been resized like in:

public class BindStackPaneToScene extends Application {
    Shape union;
    Shape makeShape(double w, double h) {
        Rectangle smallShape = new Rectangle(0, 3, 50, 50);
        smallShape.setArcHeight(6);
        smallShape.setArcWidth(6);

        Rectangle bigRectangle = new Rectangle(25, 3, w/2, h/2);
        bigRectangle.setArcHeight(10);
        bigRectangle.setArcWidth(10);

        Shape unionShape = Shape.union(smallShape, bigRectangle);
        unionShape.setFill(Color.rgb(0, 0, 0, .50));
        unionShape.setStroke(Color.BLUE);

        return unionShape;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        StackPane stackPane = new StackPane();
        stackPane.setPrefHeight(200);
        stackPane.setPrefWidth(200);
        stackPane.setStyle("-fx-background-color: BEIGE");

        union = makeShape(200,200);

        Group shapeGroup = new Group();
        shapeGroup.getChildren().add(union);
        stackPane.getChildren().add(shapeGroup);

        stackPane.heightProperty().addListener((p, o, n) -> {
            if (union != null) shapeGroup.getChildren().remove(union);
            union = makeShape(stackPane.getWidth(),  n.doubleValue());
            shapeGroup.getChildren().add(union);
        });

        Group paneGroup = new Group();
        paneGroup.getChildren().add(stackPane);

        Scene scene = new Scene(paneGroup, 400, 400,Color.LIGHTSKYBLUE);
        stackPane.prefHeightProperty().bind(scene.heightProperty().divide(1));
        stackPane.prefWidthProperty().bind(scene.widthProperty().divide(1));
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}