我想让我的申请流畅。但是,当我将窗口放大时,与UI元素相比,字体看起来很小。最终,当我调整窗口大小时,我希望文本的大小变大或变小。我知道理论上我可以使用style属性执行此操作,但在某些情况下我已将该属性绑定到其他位置。
我知道有“fontProperty”方法,但我没有任何东西可以绑定它,因为我无法弄清楚如何创建一个具有同步大小的动态ObjectProperty。我该怎么办?
编辑:为了避免混淆,我试图根据其他因素改变字体大小,而不是相反。
答案 0 :(得分:12)
只需将所有想要字体大小的内容放在容器中,然后根据需要设置该样式或使用绑定。
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值。
答案 1 :(得分:8)
设置.root -fx-font-size
在sylesheet .root
选择器中,将-fx-font-size
设置为您想要的值:
.root { -fx-font-size:40px; }
为什么会这样?
这是因为:
em
单位(基于默认字体大小)。-fx-font-size
是一种inherited风格。执行此操作后,所有控件(及其中的文本)将自动调整大小以适合您指定的任何字体大小。
相关示例
相关信息
em
是一个非特定于JavaFX的通用单元,em单元也用于HTML CSS。如果有兴趣,您可以阅读broader discussion on em units versus other units。
通过表达式绑定在FXML中使用em单位
只需设置默认字体大小就可以获得所需位置的90%左右,但不一定是通用修复,因为某些布局单元可能指定不使用em单位。大部分时间这不是一个真正的问题,但如果是在你的情况下,你也可以应用Oracle developer mailing list post中描述的机制,这似乎有效,但有点笨拙。
如何使用表达式绑定。
对于35em x 25em,你可以写:
prefWidth="${35*u.em}" prefHeight="${25*u.em}"
它不是100%简洁,但也许可以通过。
这种大小调整表达式适用于场景构建器1.1,这很不错。
以下是使用Rectangle存储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>
答案 2 :(得分:3)
有一种最简单的方法可以将字体大小与容器大小绑定,以使其具有响应的字体缩放效果。
bind(Bindings.concat("-fx-font-size: "
是一个不错的选择,但是当你调整窗口大小时,它似乎非常慢,我认为这不是解决问题的正确方法。
您可以声明FontProperty并将此FontProperty绑定到Component(Label,Text等),最后创建一个事件,根据我们的设计将大小与FontProperty大小绑定:
private Label textTracking = new Label();
private ObjectProperty<Font> fontTracking = new SimpleObjectProperty<Font>(Font.getDefault());
然后在构造函数或某些init方法中,您可以使用我们的动态字体绑定对象的font属性:
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: "
方法。
答案 3 :(得分:0)
我遇到了类似的问题,并通过以下方式解决了该问题:
之所以起作用,是因为设置在主窗格中的样式将影响FXML中已经定义的所有节点作为修饰符。已经具有样式类的节点也会受到影响,因为新样式会在级联样式表中作为样式的附加顶层提供。
此解决方案的主要优点是可以在单个位置处理字体大小缩放因子。因此,您不必查找每个具有Font属性的节点即可使其工作。
示例文件:
styles.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("%;"));
}
});
}
}