Search code examples
javafxdata-bindingproperties

Updating Labels to show the width and height of the scene in JavaFX


I'm trying to make a small JavaFX program that prints out the width and height of the current window, and updates it automatically using properties and bindings.

I tried a lot of things, and came to this solution:

import javafx.application.Application;

import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class App extends Application {


    @Override
    public void start(Stage stage) {
        VBox root = new VBox();
        Label width = new Label();
        Label height = new Label();
        TextField widthTf = new TextField();
        TextField heightTf = new TextField();
        Button button = new Button("Resize");
        root.getChildren().addAll(width, height, widthTf, heightTf, button);

        IntegerProperty widthInteger = new SimpleIntegerProperty(320);
        IntegerProperty heightInteger = new SimpleIntegerProperty(240);

        Scene scene = new Scene(root, widthInteger.getValue(), heightInteger.getValue());

        width.textProperty().bind(widthInteger.asString());
        height.textProperty().bind(heightInteger.asString());

        stage.setScene(scene);
        button.setOnAction(e -> {
            widthInteger.setValue(Integer.parseInt(widthTf.getText()));
            heightInteger.setValue(Integer.parseInt(heightTf.getText()));
            stage.setWidth(widthInteger.getValue());
            stage.setHeight(heightInteger.getValue());
            widthTf.clear();
            heightTf.clear();
        });

        stage.show();
    }

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

It is definitely not pleasing to the eyes, but that is not my main goal here, and even tho using the button does update the values and resize the window, it just feels like cheating to me. I'm pretty sure there has to be a better way than this, and if there is, I would like to know what exactly. I tried using scene.getWidth() and scene.getHeight(), but I couldn't solve it with them. I might be just overthinking this, but it definitely feels like a cheating solution and like there is a better and cleaner way.

Thanks for the help in advance.


Solution

  • If the goal is simply to have labels which display the width and height of the window, Stage exposes a widthProperty() and a heightProperty(). You can just bind directly to those:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class App extends Application {
    
    
        @Override
        public void start(Stage stage) {
            VBox root = new VBox();
            Label width = new Label();
            Label height = new Label();
            root.getChildren().addAll(width, height);
    
            Scene scene = new Scene(root, 320, 240);
    
            width.textProperty().bind(stage.widthProperty().asString());
            height.textProperty().bind(stage.heightProperty().asString());
    
            stage.setScene(scene);
    
    
            stage.show();
        }
    
        public static void main(String[] args) { launch(args);}
    }
    

    If you want them as integers, you can provide a format string:

    width.textProperty().bind(stage.widthProperty().asString("%.0f"));
    

    etc.