如何动态更改 UI 中的字体大小以在 JavaFX 中始终保持相同的宽度?
How to dynamically change font size in UI to always be the same width in JavaFX?
我想做的是使用 Scenebuilder 在 fxml 中创建一个标签,它会更新其字体大小以始终确保标签的内容大小相同。
一些背景信息是我正在使用 AnchorPane
,它已最大化且不可调整大小。
我不需要文本的高度相同——只是宽度相同。另外,我只想调整大小 如果它太大而不适合 。所以如果标签只有 1 个字母,我不希望它是一个巨大的单个字母。我只有初步的想法,下面是一些伪代码。谢谢!
lengthOfLabel = menuLabel.getText().length();
if(lengthOfLabel > numOfCharsThatCanFitInWidth){
menuLabel.setStyle("-fx-font-size: " + (int) (someConstant/lengthOfLabel) + ";")
}
您可以使用临时 Text
object 来测量文本大小,如果不适合则缩放字体。像这样:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
//maximum width of the text/label
private final double MAX_TEXT_WIDTH = 400;
//default (nonscaled) font size of the text/label
private final double defaultFontSize = 32;
private final Font defaultFont = Font.font(defaultFontSize);
@Override
public void start(Stage primaryStage) {
final TextField tf = new TextField("Label text goes here");
final Label lbl = new Label();
lbl.setFont(defaultFont);
lbl.textProperty().addListener((observable, oldValue, newValue) -> {
//create temp Text object with the same text as the label
//and measure its width using default label font size
Text tmpText = new Text(newValue);
tmpText.setFont(defaultFont);
double textWidth = tmpText.getLayoutBounds().getWidth();
//check if text width is smaller than maximum width allowed
if (textWidth <= MAX_TEXT_WIDTH) {
lbl.setFont(defaultFont);
} else {
//and if it isn't, calculate new font size,
// so that label text width matches MAX_TEXT_WIDTH
double newFontSize = defaultFontSize * MAX_TEXT_WIDTH / textWidth;
lbl.setFont(Font.font(defaultFont.getFamily(), newFontSize));
}
});
lbl.textProperty().bind(tf.textProperty());
final AnchorPane root = new AnchorPane(lbl, tf);
AnchorPane.setLeftAnchor(tf, 0d);
AnchorPane.setRightAnchor(tf, 0d);
AnchorPane.setBottomAnchor(tf, 0d);
primaryStage.setScene(new Scene(root, MAX_TEXT_WIDTH, 200));
primaryStage.show();
}
}
请注意 tmpText.getLayoutBounds()
returns 不包含任何 transformations/effects 的边界(如果需要这些,您必须将文本 object 添加到临时场景并在 parent).
中计算其边界
我想做的是使用 Scenebuilder 在 fxml 中创建一个标签,它会更新其字体大小以始终确保标签的内容大小相同。
一些背景信息是我正在使用 AnchorPane
,它已最大化且不可调整大小。
我不需要文本的高度相同——只是宽度相同。另外,我只想调整大小 如果它太大而不适合 。所以如果标签只有 1 个字母,我不希望它是一个巨大的单个字母。我只有初步的想法,下面是一些伪代码。谢谢!
lengthOfLabel = menuLabel.getText().length();
if(lengthOfLabel > numOfCharsThatCanFitInWidth){
menuLabel.setStyle("-fx-font-size: " + (int) (someConstant/lengthOfLabel) + ";")
}
您可以使用临时 Text
object 来测量文本大小,如果不适合则缩放字体。像这样:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
//maximum width of the text/label
private final double MAX_TEXT_WIDTH = 400;
//default (nonscaled) font size of the text/label
private final double defaultFontSize = 32;
private final Font defaultFont = Font.font(defaultFontSize);
@Override
public void start(Stage primaryStage) {
final TextField tf = new TextField("Label text goes here");
final Label lbl = new Label();
lbl.setFont(defaultFont);
lbl.textProperty().addListener((observable, oldValue, newValue) -> {
//create temp Text object with the same text as the label
//and measure its width using default label font size
Text tmpText = new Text(newValue);
tmpText.setFont(defaultFont);
double textWidth = tmpText.getLayoutBounds().getWidth();
//check if text width is smaller than maximum width allowed
if (textWidth <= MAX_TEXT_WIDTH) {
lbl.setFont(defaultFont);
} else {
//and if it isn't, calculate new font size,
// so that label text width matches MAX_TEXT_WIDTH
double newFontSize = defaultFontSize * MAX_TEXT_WIDTH / textWidth;
lbl.setFont(Font.font(defaultFont.getFamily(), newFontSize));
}
});
lbl.textProperty().bind(tf.textProperty());
final AnchorPane root = new AnchorPane(lbl, tf);
AnchorPane.setLeftAnchor(tf, 0d);
AnchorPane.setRightAnchor(tf, 0d);
AnchorPane.setBottomAnchor(tf, 0d);
primaryStage.setScene(new Scene(root, MAX_TEXT_WIDTH, 200));
primaryStage.show();
}
}
请注意 tmpText.getLayoutBounds()
returns 不包含任何 transformations/effects 的边界(如果需要这些,您必须将文本 object 添加到临时场景并在 parent).