我想让我的申请变得流畅。但是,当我将窗口变大时,与 UI 元素相比,字体看起来很小。最终,我希望在调整窗口大小时文本的大小变大或变小。我知道理论上我可以使用 style 属性来做到这一点,但在某些情况下我已经将该属性绑定到其他内容。
我知道有“fontProperty”方法,但我没有任何东西可以绑定到它,因为我不知道如何创建具有同步大小的动态 ObjectProperty。我该怎么办?
编辑:为了避免混淆,我试图根据其他因素来改变字体大小,而不是相反。
只需将所有想要更改字体大小的内容放入容器中,然后设置该样式或根据需要使用绑定。
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);
}
}
我不确定你的样式已经绑定到什么,但你可以在样式字符串中设置多个 css 值。
设置.root -fx-font-size
为您的应用程序创建一个自定义样式表。
在 sylesheet
.root
选择器中,将 -fx-font-size
设置为您想要的值:
.root { -fx-字体大小:40px; }
如果需要,可以按照
Stylesheet API中的描述使用
data:
URI 将样式表数据设置为字符串值。 这允许您以编程方式创建样式表数据,并根据需要在运行时应用它(例如,对于不同的计算字体大小)。
为什么这有效
这之所以有效,是因为:
一旦执行此操作,所有控件(以及其中的文本)将自动调整大小以适合您指定的任何字体大小。
相关样本
相关资讯
em
是一个通用单位,并非特定于 JavaFX,em 单位也用于 HTML CSS 中。 如果有兴趣,您可以阅读有关 em 单位与其他单位的更广泛讨论。
通过表达式绑定在 FXML 中使用 em 单位
仅设置默认字体大小即可使您达到所需位置的大约 90%,但不一定是通用修复,因为某些布局单位可能不使用 em 单位指定。 大多数情况下,这并不是真正的问题,但如果是您的情况,您还可以应用 Oracle 开发人员邮件列表帖子中描述的机制,该机制似乎有效,但有点笨拙。
使用表达式绑定怎么样。
对于 35em x 25em 你可以写:
prefWidth="${35*u.em}" prefHeight="${25*u.em}"
它不是 100% 简洁,但也许还过得去。
这些尺寸表达式可以在场景构建器 1.1 中使用,这很好。
这里是一个使用矩形来存储 fxml 文件的宽度和高度修饰符的示例。
<?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>
或者,您可以创建自己的单位类并在大小调整表达式中使用它,例如:
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>
有一个最简单且正确的方法,将字体大小与容器大小绑定,以使其达到响应式字体缩放效果。
bind(Bindings.concat("-fx-font-size: "
是一个很好的选择,但是当您调整窗口大小时,它似乎非常慢,我认为这不是解决问题的正确方法。
您可以声明 FontProperty 并将此 FontProperty 绑定到组件(Label、Text 等),最后根据我们的设计创建一个事件将大小与 FontProperty 大小绑定:
private Label textTracking = new Label();
private ObjectProperty<Font> fontTracking = new SimpleObjectProperty<Font>(Font.getDefault());
然后在构造函数或某些 init 方法中,您可以将对象的字体属性与动态字体绑定:
textTracking.fontProperty().bind(fontTracking);
最后,需要将包装容器更改大小与动态字体大小绑定:
widthProperty().addListener(new ChangeListener<Number>()
{
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldWidth, Number newWidth)
{
fontTracking.set(Font.font(newWidth.doubleValue() / 4));
}
});
使用此解决方案,动态字体调整非常流畅且快速,甚至比
bind(Bindings.concat("-fx-font-size: "
方法还要好。
我也遇到了类似的问题,是这样解决的:
它之所以有效,是因为为主窗格设置的样式将作为修饰符影响 FXML 中已定义的所有节点。已经具有样式类的节点也会受到影响,因为新样式作为级联样式表中附加的顶层样式出现。
该解决方案的主要优点是在单个位置处理字体大小缩放系数。因此,您不必找到每个具有 Font 属性的节点即可使其正常工作。
示例文件:
样式.css
.label {
-fx-font-size: 1.1em;
}
.title {
-fx-font-size: 1.5em;
-fx-font-weight: bold;
}
main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.layout.*?>
<BorderPane style="-fx-background-color: #fff;"
xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
prefWidth="1280.0" prefHeight="720.0"
fx:controller="controllers.MainController">
<top>
<Label text="Application title" styleClass="title"/>
</top>
<center>
<Label text="Lorem ipsum"/>
</center>
</BorderPane>
MainController.java
package controllers;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.BorderPane;
public class MainController implements Initializable {
@FXML private BorderPane mainPane;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
initializeFontSizeManager();
}
private void initializeFontSizeManager() {
// Cf. https://stackoverflow.com/questions/13246211/javafx-how-to-get-stage-from-controller-during-initialization
mainPane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
// We need a scene to work on
if (oldScene == null && newScene != null) {
DoubleProperty fontSize = new SimpleDoubleProperty(0);
fontSize.bind(newScene.widthProperty().add(newScene.heightProperty())
.divide(1280 + 720) // I know, it's a very rough approximation :)
.multiply(100)); // get a suitable value to put before the '%' symbol in the style
mainPane.styleProperty().bind(
Bindings.concat("-fx-font-size: ", fontSize.asString("%.0f")).concat("%;"));
}
});
}
}
我知道这是一个很老的问题 但从 19-ea+9 开始你可以使用 like
private DoubleProperty fontSize = new SimpleDoubleProperty(10);
node.styleProperty().bind(fontSize.map(size -> "-fx-font-size: "+size+";-fx-base: rgb(0,0,255);"));