Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFx USE_COMPUTED_SIZE for Stage without using FXML

In the JavaFX Scene Builder, I can select a value for the minimum, maximum and preferred width and height of a Control or Container. There are predefined values like USE_COMPUTED_SIZE.

I came to the conclusion, that I don't like to use FXML for my current project, for several reasons and now I am wondering how to set those values when not using FXML.

How do I do this?

I've tried the following code:

initializeControls();
addControls();


setMinHeight(Control.USE_COMPUTED_SIZE);
setMinWidth(Control.USE_COMPUTED_SIZE);

addActionListeners();
addFocusChangeListeners();

However, that results in an Exception when trying to create the Stage:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: The width and height must be >= 0. Got: width=-1; height=-1
at com.sun.glass.ui.Window.setMinimumSize(Window.java:984)
at com.sun.javafx.tk.quantum.WindowStage.setMinimumSize(WindowStage.java:291)
at javafx.stage.Stage.impl_visibleChanging(Stage.java:1154)
at javafx.stage.Window$9.invalidated(Window.java:743)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:143)
at javafx.stage.Window.setShowing(Window.java:841)
at javafx.stage.Window.show(Window.java:856)
at javafx.stage.Stage.show(Stage.java:255)
at dictionary.MainApp.trainVocablesButtonActionPerformed(MainApp.java:281)
at dictionary.MainApp.lambda$addActionListeners$2(MainApp.java:240)
at dictionary.MainApp$$Lambda$281/81350454.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8216)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3724)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3452)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1728)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2461)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:348)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:273)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:382)
at com.sun.glass.ui.View.handleMouseEvent(View.java:553)
at com.sun.glass.ui.View.notifyMouse(View.java:925)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$45(GtkApplication.java:126)
at com.sun.glass.ui.gtk.GtkApplication$$Lambda$42/379110473.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)

I guess, that I took the USE_COMPUTED_SIZE value from the wrong class or something, but where do I get the correct value from? Or is this whole approach somehow wrong?

My ultimate goal is to make the stage take as much space as is needed to display all the controls and containers in it, but not more.

EDIT#1: Correction: It should take as much space as needed as a Minimum width and height, so that the window is still resizeable but cannot be made so small that controls are not displayed any more.

EDIT#2: Result of trying to set the minimum width + height on a smaller example app: enter image description here

Code:

package javafxapplication3;

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.paint.RadialGradientBuilder;
import javafx.scene.paint.Stop;
import javafx.stage.Stage;

public class GridPaneExample extends Application {
private final Paint background = RadialGradientBuilder.create()
            .stops(new Stop(0d, Color.TURQUOISE), new Stop(1, Color.web("3A5998")))
            .centerX(0.5d).centerY(0.5d).build();
    @Override
    public void start(Stage primaryStage) {
        GridPane root = new GridPane();
        root.setPadding(new Insets(5));
        root.setHgap(2);
        root.setVgap(2);
        root.setAlignment(Pos.CENTER);
        final TextField tex = new TextField();
        tex.setPrefWidth(250);
        tex.setPrefHeight(50);
        tex.setPromptText("Press the buttons to Display text here");
        tex.setFocusTraversable(false);
        GridPane.setColumnSpan(tex, 7);
        GridPane.setRowSpan(tex, 2);
        root.add(tex, 0, 0);
        GridPane.setHalignment(tex, HPos.CENTER);
        final Button[][] btn = new Button[5][5];
        char ch = 'A';
        for ( int i = 0; i < btn.length; i++) {
            for ( int j = 0; j < btn.length; j++) {

                btn[i][j] = new Button("" + ch);
                btn[i][j].setPrefSize(50, 50);
                root.add(btn[i][j], j, i+2);
                ch++;
                btn[i][j].setOnMouseClicked((mouseEvent) -> {
                    Button b = (Button) mouseEvent.getSource();
                    tex.appendText(b.getText());
                });
            }
        }

        Scene scene = new Scene(root,background);

        primaryStage.setTitle("Grid Pane Example");


        primaryStage.setScene(scene);

        primaryStage.setWidth(Control.USE_COMPUTED_SIZE);
        primaryStage.setHeight(Control.USE_COMPUTED_SIZE);

        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
like image 713
Zelphir Kaltstahl Avatar asked Feb 18 '15 00:02

Zelphir Kaltstahl


1 Answers

One of the comments helped me to find a solution, although it might not be the best solution: After adding all controls to the scene I simply can do the following:

setMinWidth(getWidth());
setMinHeight(getHeight());

This works because JavaFX initially sets the stage to a size needed by the controls on its scene.

like image 57
Zelphir Kaltstahl Avatar answered Sep 21 '22 20:09

Zelphir Kaltstahl