JavaFX sizeToScene() 不尊重舞台的最大值

问题描述 投票:0回答:1

当我在设置了最大尺寸的透明窗口上调用

sizeToScene
时遇到问题。

假设我将 StackPane 的 prefWidth 设置为大于舞台的 maxWidth。当我显示舞台时,它会考虑舞台的最大宽度并相应地调整 StackPane 宽度。但之后,如果我为 StackPane 设置相同的 prefWidth(或者实际上任何大于 Stage 的 maxWidth 的值)并调用 sizeToScene(),内容舞台将以不同的方式呈现。

在下面的演示中,我将透明舞台最大宽度设置为 200px。并将 StackPane prefWidth 设置为 300px。当舞台显示时,StackPane 将其宽度调整为 200px,这很好。

当我单击标签时,如果我调用 sizeToScene,则内容宽度将根据 prefSizes 进行更新,并且不考虑舞台的最大值。

enter image description here

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class SizeToSceneOnTransparentWindow_Demo extends Application {

    Stage stage;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button show = new Button("Show");
        show.setOnAction(e -> {
            if(stage==null) {
                stage = new Stage();
                stage.initStyle(StageStyle.TRANSPARENT);
                stage.setMaxWidth(200);

                Label label = new Label("Test");
                StackPane container = new StackPane(label);
                container.setStyle("-fx-background-color:#FF000050;-fx-border-width:2px;-fx-border-color:#888888;");
                container.setPrefSize(300, 300);

                label.setOnMouseClicked(e1 -> {
                    stage.sizeToScene();
                });

                StackPane root = new StackPane(container);
                stage.setScene(new Scene(root));
                stage.setX(200);
                stage.setY(200);
            }
            stage.show();
        });
        Button hide = new Button("Hide");
        hide.setOnAction(e -> stage.hide());

        Scene scene = new Scene(new HBox(10,show, hide), 200,200);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

这是一个 JavaFX 错误还是应该有这样的行为?因为我观察到 sizeToScene() 方法是在

Window
类中定义的,最大尺寸是在
Stage
类中定义的,很明显 sizeToScene() 方法不会考虑最大值。

sizeToScene 的文档如下:

设置此窗口的宽度和高度以匹配窗口的大小 此窗口场景的内容。

如果窗口不允许这样做,则此请求可能会被忽略, 例如,舞台可能会最大化或全屏,因此 不允许此请求。如果是这样的话,这个请求就是 记住并在允许的情况下重新应用。

文档说明了有关调整窗口大小的信息,但在上述情况下,情况并非如此。场景或内容已调整大小。

javafx
1个回答
0
投票

这似乎是一个错误,如果您愿意,您可以将其归档

您可以通过设置场景根的最大尺寸来解决这个问题,例如:

Node root = stage.getScene().getRoot();

设置一次值:

root.setMaxWidth(stage.maxWidthProperty());

追踪价值:

root.maxWidthProperty().bind(stage.maxWidthProperty());

如果您还想考虑舞台或窗口最大/最小函数中的场景变化,那么事情会更复杂。

常见问题解答

因为我观察到 sizeToScene() 方法是在 Window 类中定义的,而最大尺寸是在 Stage 类中定义的,很明显 sizeToScene() 方法不会考虑最大值。

它并不像看起来那么明显,因为 sizeToScene 的实现委托给辅助方法。 此外,Stage(或 Stage 子类中的代码)可以覆盖 sizeToScene,尽管 stage 在 JavaFX 23 中不会这样做。

如果你好奇的话,Window中更改句柄大小的代码是:

/**
 * Indicates if a user requested the window to be sized to match the scene
 * size.
 */
private boolean sizeToScene = false;
/**
 * Set the width and height of this Window to match the size of the content
 * of this Window's Scene.
 */
public void sizeToScene() {
    if (getScene() != null && peer != null) {
        SceneHelper.preferredSize(getScene());
        adjustSize(false);
    } else {
        // Remember the request to reapply it later if needed
        sizeToScene = true;
    }
}

private void adjustSize(boolean selfSizePriority) {
    if (getScene() == null) {
        return;
    }
    if (peer != null) {
        double sceneWidth = getScene().getWidth();
        double cw = (sceneWidth > 0) ? sceneWidth : -1;
        double w = -1;
        if (selfSizePriority && widthExplicit) {
            w = getWidth();
        } else if (cw <= 0) {
            w = widthExplicit ? getWidth() : -1;
        } else {
            widthExplicit = false;
        }
        double sceneHeight = getScene().getHeight();
        double ch = (sceneHeight > 0) ? sceneHeight : -1;
        double h = -1;
        if (selfSizePriority && heightExplicit) {
            h = getHeight();
        } else if (ch <= 0) {
            h = heightExplicit ? getHeight() : -1;
        } else {
            heightExplicit = false;
        }

        peerBoundsConfigurator.setSize(w, h, cw, ch);
        applyBounds();
    }
}

当舞台显示或场景无效时,传递给 adjustmentSize 的 selfSizePriority 为 true,因此它将尺寸优先级赋予窗口约束,但是当您调整场景大小时 selfSizePriority 为 false,它仅将尺寸优先级赋予场景约束。

© www.soinside.com 2019 - 2024. All rights reserved.