How to bind stage resizing with resizing of components?

Agafonova Victoria picture Agafonova Victoria · Apr 25, 2012 · Viewed 58.6k times · Source

I have a JavaFX 2.0 application with FXML. I want the components (TextFields, ComboBoxes, layouts, and so on) to be resized when a window with an application is resized. So...

When building GUI applications with JavaFX, you will notice that certain classes in the API already implement properties. For example, the javafx.scene.shape.Rectangle class contains properties for arcHeight, arcWidth, height, width, x, and y. For each of these properties there will be corresponding methods that match the conventions previously described. For example, getArcHeight(), setArcHeight(double), arcHeightProperty(), which together indicate (to both developers and tools) that the given property exists.*

  • To add listener to a stage I have to do something like:

       stage.resizableProperty().addListener(new ChangeListener<Boolean>(){
        @Override
        public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2){
            throw new UnsupportedOperationException("Not supported yet.");
        }
    
    });
    

So there are two questions:

  • To make some binding I have to get my stage in the controller class. So - how can I get a stage in a controller class?
  • It looks like UI controls do not have any width\height properties, to be bound to something. Or perhaps I have not found them.

So, how can I solve my problem?

UPD. About Scene Builder to Sergey Grinev: When I use Ctrl+K on my component (tell it to occupy the whole area of its parent component) - everything is ok.

But what if I want to tell my component to occupy 50% of an area? For exammple I have a tab with two VBoxes on it. The tab's width is 100px. The Vbox's widths are 50px for each. VBox1 has x1=0, and x2=50, and VBox2 has x1=50, and x2=100. Then I resize my window with JavaFX application. Now I have tab's Width = 200px. But my VBoxes widths are still = 50px: VBox1 has x1=0, and x2=50, and VBox2 has x1=150, and x2=200. And I need them to be VBox1 x1=0 and x2=100 and VBox2 x1=100 and x2=200. Where x1 and x2 values are the coordinates of VBoxes corners.

How can Scene Builder help me in this situation?

Answer

jewelsea picture jewelsea · Apr 25, 2012

Some suggestions for building resizable guis =>

  • Make sure the root of your app is a Pane subclass, rather than a Group.
  • Unclamp the max size of buttons (e.g button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE).
  • Most of the time the layout panes can handle the resizing for you and you don't need bindings and listeners => i.e. only bind when you really need to.
  • UI controls and layout panes are Regions => all Regions have read-only height and width properties you can listen to and bind to.
  • You can not directly bind the height and width properties of a control to another value. Instead use the minWidth/Height, prefWidth/Height, maxWidth/Height properties.
  • The scene has height and width properties you can bind to if needed. If you do this, when the stage is resized, the scene will be resized, then your bound components will be resized. If the root of your scene is a layout pane rather than a group, this binding is usually unnecessary.
  • If you don't set a height and width on the scene, for a stand-alone app, the scene (and stage) will be sized to fit the preferred size of the scene's root node (which is usually what you want).
  • If all else fails you can start overriding Parent's layoutchildren method.

Here is an example of a resizable JavaFX UI which implements some of the principles above.