camickr
camickr

Reputation: 324108

What is the preferred size of a control?

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

Answers (3)

J Atkin
J Atkin

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

Prometheus
Prometheus

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

eckig
eckig

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

Related Questions