0
votes

I have ImageView inside HBox inside Pane, and want ImageView height fit HBox height when resizing stage. Trying the following code

package sample;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        pane.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
        HBox hBox = new HBox();
        hBox.setBackground(new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));
        hBox.setPrefHeight(100);
        hBox.setPrefWidth(100);
        hBox.prefHeightProperty().bind(pane.heightProperty());
        ImageView imageView = new ImageView("http://www.calgary.ca/CA/city-manager/scripts/about-us/webparts/images/ourHistory_retina.jpg");
        imageView.fitHeightProperty().bind(hBox.heightProperty());
        imageView.setPreserveRatio(true);
        hBox.getChildren().add(imageView);
        pane.getChildren().add(hBox);
        primaryStage.setScene(new Scene(pane, 300, 275));
        primaryStage.show();
    }


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

When starting, ImageView is not fit windows height, it shown in it's original size. And it scales only up when I resize window to make it bigger, then original image size.

Also I see, that hBox.prefHeightProperty().bind(pane.heightProperty()) works perfectly (height of red HBox background behind image is corresponding window height).

So it seems imageView.fitHeightProperty().bind(hBox.heightProperty()) behaves not as I expecting.

How can I make ImageView fit height of HBox, nested in Pane?

2
Can you explain what you actually want to do, specifically with the height (and width) of the HBox? It looks like you want it to fill the full height (but not the width) of the pane. If so, it's probably better to use a layout pane for the root that lets you do that (instead of binding the height of the hbox to the height of the pane). For the width of the hbox, you set the pref width to 100, but the width of the image view will be determined by the image and the height of the hbox... - James_D
James, I'm trying to create simple horizontal gallery, putting images inside hbox. And I need images height exactly match HBox height when resizing HBox's parent. - Alexey

2 Answers

2
votes

In the code you posted, the HBox is actually getting taller than the root Pane that contains it (though it is getting clipped so you only see the portion in side the root). So the binding on the fitHeight is behaving as you want, but the layout with respect to the HBox's preferred height is not doing what you expect. So you need better control over the layout of the HBox.

The layout pane that allows you the most control is the GridPane. So, while it's possible there may be easier ways to do this, using a GridPane as the root and placing the HBox in the only cell at 0,0 allows you to control how the HBox is resized. The only additional thing you need here is to allow the HBox to shrink indefinitely with setMinHeight(0).

I think the following provides the behavior you want:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        GridPane root = new GridPane();

        RowConstraints rc = new RowConstraints();
        rc.setVgrow(Priority.ALWAYS);

        root.getRowConstraints().add(rc);

        root.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
        HBox hBox = new HBox();
        hBox.setBackground(new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));
        hBox.setMinHeight(0);
        ImageView imageView = new ImageView("http://www.calgary.ca/CA/city-manager/scripts/about-us/webparts/images/ourHistory_retina.jpg");
        imageView.fitHeightProperty().bind(hBox.heightProperty());
        imageView.setPreserveRatio(true);
        hBox.getChildren().add(imageView);
        root.add(hBox, 0, 0);         

        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}
0
votes

Thanks to James_D, who have suggested the solution. It's possible even remain Pane as root.

The only line to be added is

hBox.setMinHeight(0);

Also odd

hBox.setPrefHeight(100);
hBox.setPrefWidth(100);

should be removed.