Как динамически изменить размер шрифта в пользовательском интерфейсе, чтобы всегда быть одинаковой ширины в JavaFX? - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь создать метку в fxml, используя Scenebuilder, который обновляет размер шрифта, чтобы всегда гарантировать, что содержимое метки имеет одинаковый размер.

Некоторая справочная информация заключается в том, что яЯ использую AnchorPane, который является максимальным и не изменяемого размера.

Мне не нужно, чтобы высота текста была одинаковой - только ширина.Кроме того, я бы хотел изменить размер , только если он слишком большой, чтобы уместить .Поэтому, если на этикетке всего одна буква, я не хочу, чтобы она была гигантской одной буквой.У меня есть только элементарные идеи, некоторые из которых псевдокод ниже.Спасибо!

lengthOfLabel = menuLabel.getText().length();

if(lengthOfLabel > numOfCharsThatCanFitInWidth){
    menuLabel.setStyle("-fx-font-size: " + (int) (someConstant/lengthOfLabel) + ";")
}

1 Ответ

0 голосов
/ 03 февраля 2019

Вы можете использовать объект temp Text для измерения размера текста и масштабирования шрифта, если он не подходит.Примерно так:

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() возвращает границы, которые не включают каких-либо преобразований / эффектов (если они необходимы, вам придется добавить текстовый объект во временную сцену и вычислить ее границыв родительском).

Text fits Text fits, again Text scaled down

...