Bind font size in JavaFX?

I want my application to be fluid. However, fonts look small compared to user interface elements when I make windows large. Ultimately, I want my text to increase or decrease as the window resizes. I know that I can theoretically do this with the style property, but I already have this property associated with something else in some cases.

I know that the fontProperty method exists, but I have nothing to associate with it, since I cannot figure out how to create a dynamic ObjectProperty with a synchronized size. What should I do?

EDIT: To avoid confusion, I'm trying to resize the font based on other factors, not the other way around.

+7
java user-interface fonts data-binding javafx
source share
3 answers

Just put everything where you want fontsize to change in the container and set this style or use bindings if you want.

import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextArea; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class FontBind extends Application { private DoubleProperty fontSize = new SimpleDoubleProperty(10); private IntegerProperty blues = new SimpleIntegerProperty(50); @Override public void start(Stage primaryStage) { Button btn = new Button("click me, I change color"); btn.setOnAction((evt)->{blues.set(blues.get()+20);});//max? Label lbl = new Label("I'm a label"); TextArea ta = new TextArea("Lots of text can be typed\nand even number 1234567890"); HBox hbox = new HBox(new Label("I never change")); VBox child = new VBox(btn, lbl, ta); VBox root = new VBox(child, hbox); Scene scene = new Scene(root, 300, 250); fontSize.bind(scene.widthProperty().add(scene.heightProperty()).divide(50)); child.styleProperty().bind(Bindings.concat("-fx-font-size: ", fontSize.asString(), ";" ,"-fx-base: rgb(100,100,",blues.asString(),");")); primaryStage.setTitle("Hello World!"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

I'm not sure if your style is already connected, but you are allowed to set multiple css values ​​in the style line.

+10
source share

Set the size .root -fx-font-size

  • Create a custom style sheet for your application.
  • In the sylesheet .root selector, set -fx-font-size to the desired value:

    .root {-fx-font-size: 40px; }

Why does it work

This works because:

  • All default controls are based on em units (which are based on the default font size).
  • -fx-font-size is an inherited style.
  • Everything is inherited from the root.

Once you do this, all the controls (and the text inside them) will automatically resize to fit any font size you specify.

Related example

  • javafx auto resize and add buttons

Related Information

em is a common element that is not specific to JavaFX, and em units are also used in CSS CSS. If you are interested, you can read a broader discussion of em units compared to other devices .

Using em units in FXML by expression binding

Just setting the default font size gives you about 90% of where you should be, but is not necessarily a universal fix, as some layout units can be specified without using em units. In most cases, this is not a problem, but if it is in your case, you can also apply the mechanism described in the Oracle developers mailing list , which seems to work, albeit a little awkwardly.

How to use expression binding.

During 35x x 25m you can write:

 prefWidth="${35*u.em}" prefHeight="${25*u.em}" 

This is not 100% concise, but possibly walkable.

These sizing expressions work in Scenario 1.1, which is nice.


Here's an example of using a Rectangle to store width and height modifiers for an fxml file.

 <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.shape.*?> <StackPane xmlns:fx="http://javafx.com/fxml"> <fx:define> <Rectangle fx:id="s" width="13" height="13"/> </fx:define> <AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="${22 * s.width}" prefWidth="${14 * s.height}"> <children> <Button layoutX="${4 * s.width}" layoutY="${ 5 * s.height}" prefWidth="${6 * s.width}" text="Top" /> <Button layoutX="${4 * s.width}" layoutY="${10 * s.height}" prefWidth="${6 * s.width}" text="Middle" /> <Button layoutX="${4 * s.width}" layoutY="${15 * s.height}" prefWidth="${6 * s.width}" text="Bottom" /> </children> </AnchorPane> </StackPane> 

Or instead, you can create your own class of units and use it in your size expressions, for example:

 package org.jewelsea.measure; public class Measurement { private double em; public void setEm(double em) { this.em = em; } public double getEm() { return em; } } . . . <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import org.jewelsea.measure.Measurement?> <?scenebuilder-classpath-element .?> <StackPane xmlns:fx="http://javafx.com/fxml"> <fx:define> <Measurement fx:id="u" em="26.0" /> </fx:define> <AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="${22*u.em}" prefWidth="${14*u.em}"> <children> <Button layoutX="${4*u.em}" layoutY="${ 5*u.em}" prefWidth="${6*u.em}" text="Top" /> <Button layoutX="${4*u.em}" layoutY="${10*u.em}" prefWidth="${6*u.em}" text="Middle" /> <Button layoutX="${4*u.em}" layoutY="${15*u.em}" prefWidth="${6*u.em}" text="Bottom" /> </children> </AnchorPane> </StackPane> 
+8
source share

There is the simplest and most correct method for matching the font size with the size of the container to make it a sensitive scale effect.

bind(Bindings.concat("-fx-font-size: " is a good alternative, but when resizing windows it seems very slow, and I think this is not the right way to solve the problem.

You can declare FontProperty and associate this FontProperty with the component (Label, Text, etc.) and, finally, create an event to snap the size with the FontProperty size according to our design:

 private Label textTracking = new Label(); private ObjectProperty<Font> fontTracking = new SimpleObjectProperty<Font>(Font.getDefault()); 

Then, in the constructor or some init method, you can associate the font property of our object with our dynamic font:

 textTracking.fontProperty().bind(fontTracking); 

Finally, you need to associate the container size change of the container with the dynamic font size:

  widthProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldWidth, Number newWidth) { fontTracking.set(Font.font(newWidth.doubleValue() / 4)); } }); 

With this solution, dynamically adjusting the font is very fast and fast, even more so than bind(Bindings.concat("-fx-font-size: " .

+3
source share

All Articles