Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX - BorderPane/StackPane not resizing after children changed

I am having a resize issue when content is added and removed from a JavaFX BorderPane. The BorderPane content is not being resized until the window is manually resized. I have written a small test app to model this behavior. The application builds a BorderPane that contains a rectangle embedded within a StackPane at the center of the BorderPane. Along the bottom of the BorderPane there is a VBox and HBox that contain text and a separator. There is a menu item that removes the content from the bottom of the BorderPane (MoveText -> Right) and adds similar content to the right position of the BorderPane.

When the text is added to the right position of the BorderPane, the rectangle overlaps the text. In otherwords the content of the BorderPane center is overlapping the content in the BorderPane right.

I saw the following link - https://stackoverflow.com/questions/5302197/javafx-bug-is-there-a-way-to-force-repaint-this-is-not-a-single-threading-pr Calling requestLayout does not seem to help. I have also tried calling impl_updatePG and impl_transformsChanged on various nodes in the graph. I got this idea from this thread - https://forums.oracle.com/forums/thread.jspa?threadID=2242083

public class BorderPaneExample extends Application
{
   private BorderPane root;
   private StackPane centerPane;

   @Override
   public void start(Stage primaryStage) throws Exception
   {
      root = new BorderPane();
      root.setTop(getMenu());
      root.setBottom(getBottomVBox());
      centerPane = getCenterPane();
      root.setCenter(centerPane);

      Scene scene = new Scene(root, 900, 500);
      primaryStage.setTitle("BorderPane Example");
      primaryStage.setScene(scene);
      primaryStage.show();
   }

   private MenuBar getMenu()
   {
      MenuBar menuBar = new MenuBar();

      MenuItem rightMenuItem = new MenuItem("Right");
      rightMenuItem.setOnAction(new EventHandler<ActionEvent>() {
         @Override
         public void handle(ActionEvent actionEvent) {
            root.setRight(getRightHBox());
            root.setBottom(null);
            root.requestLayout();
         }
      });
      MenuItem bottomMenuItem = new MenuItem("Bottom");
      bottomMenuItem.setOnAction(new EventHandler<ActionEvent>() {
         @Override
         public void handle(ActionEvent actionEvent) {
            root.setRight(null);
            root.setBottom(getBottomVBox());
         }
      });

      Menu menu = new Menu("Move text");
      menu.getItems().add(rightMenuItem);
      menu.getItems().add(bottomMenuItem);
      menuBar.getMenus().addAll(menu);

      return menuBar;
   }

   private HBox getRightHBox()
   {
      HBox hbox = new HBox();

      VBox vbox = new VBox(50);
      vbox.setPadding(new Insets(0, 20, 0, 20));
      vbox.setAlignment(Pos.CENTER);

      vbox.getChildren().addAll(new Text("Additional Info 1"),
        new Text("Additional Info 2"), new Text("Additional Info 3"));
      hbox.getChildren().addAll(new Separator(Orientation.VERTICAL), vbox); 

      return hbox;
   }

   private VBox getBottomVBox()
   {
      VBox vbox = new VBox();

      HBox hbox = new HBox(20);
      hbox.setPadding(new Insets(5));
      hbox.setAlignment(Pos.CENTER);

      hbox.getChildren().addAll(new Text("Footer Item 1")
            , new Text("Footer Item 2"), new Text("Footer Item 3"));
      vbox.getChildren().addAll(new Separator(), hbox);

      return vbox;
   }

   private StackPane getCenterPane()
   {
      StackPane stackPane = new StackPane();
      stackPane.setAlignment(Pos.CENTER);

      final Rectangle rec = new Rectangle(200, 200);
      rec.setFill(Color.DODGERBLUE);
      rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
      rec.heightProperty().bind(stackPane.heightProperty().subtract(50));

      stackPane.getChildren().addAll(rec);

      return stackPane;
   }

   public static void main(String[] args)
   {
      Application.launch(args);
   }
}

Any suggestions would be appreciated. Thanks

like image 515
remery Avatar asked Dec 09 '22 15:12

remery


1 Answers

For the sake of having an answer:

The StackPane needs to have its minimum size set in order to do clipping. So if you explicitly add stackPane.setMinSize(0, 0); to the getCenterPane() method, it should fix your problem.

So your getCenterPane() method would now look like this:

private StackPane getCenterPane()
{
  StackPane stackPane = new StackPane();
  stackPane.setMinSize(0, 0);
  stackPane.setAlignment(Pos.CENTER);

  final Rectangle rec = new Rectangle(200, 200);
  rec.setFill(Color.DODGERBLUE);
  rec.widthProperty().bind(stackPane.widthProperty().subtract(50));
  rec.heightProperty().bind(stackPane.heightProperty().subtract(50));

  stackPane.getChildren().addAll(rec);

  return stackPane;
}
like image 158
Nick Rippe Avatar answered Dec 28 '22 08:12

Nick Rippe