在 JavaFX 中使用按钮自动缩放按钮的文本



我在JavaFX中制作了一个按钮网格。
当我调整内部带有网格的窗口大小时,按钮也会在网格内调整大小。
问题是这些按钮上的文本不会随之调整大小:它始终保持相同的大小,所以当按钮变大时,按钮上有很多空白空间,然后中间有一小段文字,看起来很糟糕。
我宁愿希望文本与这些按钮一起自动调整大小以适应空白空间,以便当整个用户界面变大时,按钮上的文本也会变大。
我怎样才能做到这一点?

我尝试将 CSS 样式表中的-fx-font-size设置为百分比值,但它的工作方式似乎与网站不同:文本不是按其容器的百分比缩放,而是作为某些预定义文本大小的百分比缩放。

编辑
这不是重复的!停止将每个问题标记为重复!如果已经回答了,我一开始就不会问了!

据我所知,这些线程中的第一个是关于有人想要为新创建的按钮设置文本的大小/样式以考虑其容器等的当前大小的情况。这不是我需要的,因为我希望已经创建的按钮也能够在这些按钮以某种方式在其容器内调整大小时自动调整其文本大小。

另一个线程是关于使用预设字体大小缩放文本以及根容器/窗口。这也与我需要的不同,因为我不希望文本随窗口缩放,而是随按钮本身的大小缩放。它必须以某种方式缩放:始终适合按钮的大小。你知道:文本保持不变,但拉伸以使其始终适合按钮的内部(带有一点填充,而不是文本周围的巨大空白区域(。

它是按钮的大小,用于确定其上文本的大小,而不是窗口或容器

或其他东西,并且它需要由按钮本身(内置按钮或子类化按钮(自动完成,而不是手动通过其包含的容器迭代所有这些按钮并更新其文本的大小(这将是愚蠢的方法(。

就像链接的问题一样,这是一个黑客:但请考虑缩放按钮内的文本节点,而不是更改字体大小。这似乎工作正常:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class ScaledButtons extends Application {
    @Override
    public void start(Stage primaryStage) {
        GridPane root = new GridPane();
        root.setHgap(5);
        root.setVgap(5);
        for (int i = 1; i <= 9 ; i++) {
            root.add(createScaledButton(Integer.toString(i)), (i-1) % 3, (i-1) / 3);
        }
        root.add(createScaledButton("#"), 0, 3);
        root.add(createScaledButton("0"), 1, 3);
        root.add(createScaledButton("*"), 2, 3);
        primaryStage.setScene(new Scene(root, 250, 400));
        primaryStage.show();
    }
    private Button createScaledButton(String text) {
        Button button = new Button(text);
        GridPane.setFillHeight(button, true);
        GridPane.setFillWidth(button, true);
        GridPane.setHgrow(button, Priority.ALWAYS);
        GridPane.setVgrow(button, Priority.ALWAYS);
        button.layoutBoundsProperty().addListener((obs, oldBounds, newBounds) -> 
            scaleButton(button));
        button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        return button ;
    }
    private void scaleButton(Button button) {
        double w = button.getWidth();
        double h = button.getHeight();
        double bw = button.prefWidth(-1);
        double bh = button.prefHeight(-1);
        if (w == 0 || h == 0 || bw == 0 || bh == 0) return ;
        double hScale = w / bw ;
        double vScale = h / bw ;
        double scale = Math.min(hScale, vScale);
        button.lookup(".text").setScaleX(scale);
        button.lookup(".text").setScaleY(scale);
    }
    public static void main(String[] args) {
        launch(args);
    }
}

获得类似效果的另一种方法是子类com.sun.javafx.scene.control.skin.ButtonSkin并从皮肤的父级(LabeledSkinBase(覆盖layoutLabelInArea(double x, double y, double w, double h, Pos alignment)方法。 然后,您可以将更新的外观显式分配给按钮(通过 CSS 或 Java API 调用(。

这样做需要对com.sun API 进行子类化,这些 API 可能会在后续 JavaFX 发行版中更改,恕不另行通知。 此外layoutLabelInArea操作相当复杂,因此更改布局逻辑可能有点棘手。 当然,在这种特殊情况下,James 建议基于侦听器对布局边界属性应用文本重新缩放操作更简单。

我不一定提倡这种方法,只是提供一条通往您可以创建的东西的途径,以满足您的目标:"它是按钮的大小,用于确定其上文本的大小,而不是窗口或容器或其他东西,它需要由按钮本身自动完成"。

最新更新