JavaFX : What is the proper method for scaling controls on a scene/stage/window?

标签 java javafx javafx-8 scene rescale

我有一个简单的控件,它只是一个标签和一个 VBox。目的是告知用户程序中的事情。我想使标签能够随场景正确缩放。我有适当的方法来完成这项任务(无论如何我认为):

public void reScaleX(){
    this.Message.setScaleX(( //Message is the Label Variables name.
        this.getWidth() - 40 //40 is the 20 + 20 padding given to the control.
        ) / this.Message.getBoundsInLocal().getWidth()
    );
}

public void reScaleY(){
    this.Message.setScaleY((
        this.getHeight() - 40 //40 is the 20 + 20 padding given to the control.
        ) / this.Message.getBoundsInLocal().getHeight()
    );
}

我在 Initialize 方法中为控件的 Width 和 Height 属性添加了一个监听器:

@Override public void initialize(URL location, ResourceBundle resources){
    this.widthProperty().addListener((
        ObservableValue<? extends Number> obsV, Number oldV, Number newV
    ) -> this.reScaleX());
    this.heightProperty().addListener((
        ObservableValue<? extends Number> obsV, Number oldV, Number newV
    ) -> this.reScaleY());
}

但问题是它的行为很奇怪(有时它会重新缩放,有时则不会)。我还尝试将监听器添加到放置控件的舞台的高度和宽度属性,以使其在控件调整大小时重新缩放:

    this.PreviewStage.widthProperty().addListener((
        ObservableValue<? extends Number> obsV, Number oldV, Number newV
    ) ->
        this.PreviewPlaque.reScaleX()
    ); this.PreviewStage.heightProperty().addListener((
        ObservableValue<? extends Number> obsV, Number oldV, Number newV
    ) ->
        this.PreviewPlaque.reScaleY()
    ); 

但它的行为仍然不正确。

我觉得我做错了,但我不知道如何做对。在这样的窗体上重新缩放控件的正确方法是什么?是否有更好的方法来实现我正在寻找的结果?

最佳答案

如果缩放 Label,它将对其父级产生布局影响,再次导致 width/heigt 属性发生变化,触发致命的布局递归。

我不是 100% 确定你想要实现什么。

a) 使文本以某种方式居中于可用空间:

void testLabelPlains1(VBox box) {
    box.setFillWidth(true);

    Label first = new Label("first");
    first.setAlignment(Pos.CENTER);
    first.setMaxWidth(Double.MAX_VALUE);
    first.setMaxHeight(Double.MAX_VALUE);
    VBox.setVgrow(first, Priority.ALWAYS);

    box.getChildren().addAll(first);
}

b) 在可调整大小的标签内缩放字体大小:

void testLabelPlains2(VBox box) {
    box.setFillWidth(true);

    Label first = new Label("first");
    first.setAlignment(Pos.CENTER);
    first.setMaxWidth(Double.MAX_VALUE);
    first.setMaxHeight(Double.MAX_VALUE);
    VBox.setVgrow(first, Priority.ALWAYS);

    first.heightProperty().addListener(p -> {
        first.setFont(first.getFont().font(first.getHeight()*0.7));
    });

    box.getChildren().addAll(first);
}

c) 在 X/Y 方向真正线性缩放文本

void testLabelPlains3(VBox box) {        
    Text first = new Text("first");

    box.heightProperty().addListener(p -> {
        first.setScaleY(0.8*box.getHeight()/20);
        first.setTranslateY(box.getHeight()/2);
    });
    box.widthProperty().addListener(p -> {
        first.setScaleX(0.8*box.getWidth()/30);
        first.setTranslateX(box.getWidth()/2);
    });

    box.getChildren().addAll(first);
}

...当然,硬编码的数字必须从文本的实际布局大小中得出。

关于JavaFX : What is the proper method for scaling controls on a scene/stage/window?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26768810/

相关文章:

使用自定义语言的 Javafx 国际化

java - 如何更改 JavaFX 中的 TableView 框架颜色?

JavaFX 将事件监听器附加到黑色圆圈

java - 如何在窗口关闭时关闭 JavaFX 应用程序?

java - 使用 JDBC 透视非常大的表

java - JFace 数据绑定(bind)到 Draw2d

java - 多线程连接处理

java - 使用泛型类在 Java 中进行树遍历

java - 如何在没有 JavaFX 监听器的情况下检查键是否关闭?

java - InvalidationListener 仅在带有断点的 Debug模式下执行