JavaFX: How to make my custom component use all available space from parent layout?


Question

I´m trying to make a custom component to javafx, so I make my class extends javafx.scene.control.Control and on constructor it draws it´s contents.

My doubts are: how do I make it "grow" to fill all the space available on its parent layout? Like when I place a TextArea instead...

This is an shrink example of what I´m doing:

@Override
public void start(Stage primarystage) throws Exception {
    BorderPane bpane = new BorderPane();
    mainscene = new Scene(bpane, 800, 600);
    ((BorderPane) this.mainscene.getRoot()).setCenter(t);

    primarystage.setScene(mainscene);
    primarystage.show();
}

On this example the TextArea will get all the space the layout provide for it. I want my component do the same!

All I already tried to do: - Change the properties setMaxWidth/Height, setPrefWidth/Height, setMinWidth/Height; (when I set the MinValues, it always use this values to draw but don´t update the "width" value anymore) - Tried to use Double.MAX_VALUE to force a bigger size then layout privides; Everything didn´t work :( I must be mistaking somehow... - I cried a little too, but even this make nothing work ='(

Maybe a clue is, I put a listener like this below, and everytime I resize my application/stage it updates the TextArea. But when I add this listener do my component it never get update...

TextArea t = new TextArea("teste");
t.widthProperty().addListener(new ChangeListener() {
  public void changed(ObservableValue observable, Object oldValue, Object newValue) {
    System.out.println(oldValue + "|" + newValue);
  }
});

Probably I´m passing by some properties or forgetting something, I don´t know...

I already tried Google, but seems the documentation of JavaFX is too small and superficial, and a lot of them is based on JavaFX script...

I also accepts any tutorial better them the one offered by Oracle...

Thanks in advance of any help... I thing I wrote to much... =O

1
5
3/22/2012 3:35:19 AM

Accepted Answer

I found what I was mistaking...

To make a component grow with it´s parent, all you need to do is define on maxwidth and/or maxheight it max value of double (like below), and let minwidth/height and prefwidth/height with it´s default values.

this.setMaxWidth(Double.MAX_VALUE);
this.setMaxHeight(Double.MAX_VALUE);

With this configuration when the parent changes the available space it will use the final method setWidth()/setHeight() to update the width/height your component can use. So, since these methods are final you can´t override it to "know" when a change occurs. You´ll need to add a changelistener like below to be notified when you need to repaint your component.

t.widthProperty().addListener(new ChangeListener() {
  public void changed(ObservableValue observable, Object oldValue, Object newValue) {
    System.out.println(oldValue + "|" + newValue);
  }
});
16
6/26/2018 5:04:45 PM

I found (for Java 8) - that custom controls only resize properly inside a parent node when they belong to GridPane, HBox, VBox or, preferably, to StackPane. The Oracle CustomControl example uses VBox. I could´nt get resizing to work with an AnchorPane as top node of my custom control, not even when explicitly setting maxWidth & maxHeight

So the amended CustomControl.fxml is like this:

?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. -->

<?import java.lang.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<fx:root type="javafx.scene.layout.StackPane" xmlns:fx="http://javafx.com/fxml">

  (and here inside the StackPane one can place the actual control, e.g. the 
    Anchor Pane with child nodes from ScreenBuilder -
    works without maxWidth or maxHeight)

</fx:root>

and CustomControl.java extends StackPane (instead of VBox)


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon