繁体   English   中英

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

[英]Scaling a button's text automatically with the button in JavaFX

我在JavaFX中制作了一个按钮网格。
当我调整内部带有网格的窗口的大小时,按钮也会在网格内重新调整大小。
问题在于这些按钮上的文本不会随它们调整大小:它始终保持相同的大小,因此当按钮变大时,按钮上会有很多空白,然后中间,看起来很糟糕。
我希望文本与这些按钮一起自动调整大小以适合空白区域,以便当整个用户界面变大时,按钮上的文本也变大。
我该怎么做?

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

编辑
不是重复的! 停止将每个问题标记为重复! 如果已回答,那么我一开始就不会要求它!

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

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

按钮的大小决定了文本的大小,而不是窗口或容器等的大小,它需要由按钮本身自动完成(内置按钮或子类按钮),而不是通过其包含的容器手动遍历所有这些按钮并更新其文本大小(这样做是愚蠢的方式)。

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

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子类,并从皮肤的父级重写layoutLabelInArea(double x, double y, double w, double h, Pos alignment)方法( LabeledSkinBase )。 然后,您可以显式地将更新的外观分配给按钮(通过CSS或Java API调用)。

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

我不一定要提倡这种方法,而只是提供一条可以创建的路径,该路径可以满足您的目标:“按钮的大小决定了文本的大小,而不是窗口或容器的大小。其他事情,则需要按钮本身自动完成”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM