Reputation: 324108
My first attempt at playing with JavaFX and I'm trying to understand a little bit about layout management. How do we access the preferred size of a control?
In the example below I am attempting to set the maximum width 200 pixels greater than the preferred width. That is, I want to allow the button to grow (up to a maximum) as the width of the frame is increased.
However when I run the code the preferred width is -1, so adding 200 to the preferred width gives a maximum width of 199.
import javafx.application.Application;
import javafx.event.*;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.geometry.Insets;
public class BorderPaneSSCCE extends Application
{
@Override
public void start(Stage primaryStage)
{
Button button = new Button( "Button at PreferredSize" );
button.setMaxWidth( button.getPrefWidth() + 200 );
System.out.println(button.prefWidth(-1) + " : " + button.getPrefWidth());
button.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
System.out.println("Width: " + button.getWidth());
}
});
HBox root = new HBox();
HBox.setHgrow(button, Priority.ALWAYS);
root.getChildren().add(button);
Scene scene = new Scene(root);
primaryStage.setTitle("Java FX");
primaryStage.setScene(scene);
primaryStage.show();
System.out.println(button.prefWidth(-1) + " : " + button.getPrefWidth());
}
public static void main(String[] args)
{
launch(args);
}
}
When I run the code and click on the button I see: Width: 139.0
After I resize the width of the frame so the button is as large as possible and I click on the button I see: Width: 199.0
I was hoping to see Width: 339.0
(ie. 139 + 200)
So, how do we access the preferred size/width of a control?
Upvotes: 7
Views: 10295
Reputation: 3140
-1
is the value of Region.USE_COMPUTED_SIZE
, which tells the component to figure out it's own best size. This works because every Node
has a method called prefWidth(double height)
and it's double prefHeight(double width)
(the same for min/max size) that layout managers use for calculating the layout of their children. To get the pref size you need to use
button.prefWidth([-1 or Region.USE_COMPUTED_SIZE])
(docs)
Upvotes: 4
Reputation: 1015
getPrefWidth()
returns the USE_COMPUTED_SIZE
flag (which is -1) by default.
You can use prefWidth(-1)
to get the internally computed preferred width. However the preferred width will not be calculated until the node is being layed out by the layout pane (HBox in your example). This happens the first time when the stage is shown.
You have multiple options, if you want the maximum width to depend on the preferred width. One is to set the preferred width to a fixed value with setPrefWidth()
prior to setting the maximum width.
Another is to implement a custom layout algorithm - either on the node or on a layout pane. Here is an example using a custom button.
// button whose maxWidth is always prefWidth + 200
Button button = new Button() {
@Override
protected double computeMaxWidth(double height)
{
return this.prefWidth(height) + 200.0;
}
};
Upvotes: 6
Reputation: 11134
getPrefWidth()
only works after the Node
has been shown / rendered.
You can either show the Button
first or try to use Node.prefWidth(-1)
.
Upvotes: 1