1

GridPane当我遇到以下问题时,我试图使用 a 来布局 JavaFX 阶段。如果我使用适当的约束设置网格并向其添加新实例化StackPane的 s,则场景、舞台及其内容的默认大小可确保内容可见:

没有 CSS

StackPane但是,如果我在将其添加到之前添加一个 JavaFX CSS 样式,为新实例化的新实例添加一个边框GridPane,那么默认大小的东西似乎完全崩溃了:

使用 CSS

我的代码如下:

public static void main(final String[] args) {
    Platform.startup(() -> {});
    Platform.runLater(() -> {

        final GridPane gridPane = new GridPane();
        final Scene scene = new Scene(gridPane);
        final Stage stage = new Stage();
        stage.setScene(scene);

        final List<StackPane> panes = new ArrayList<>();
        for (int i = 0; i < 4; i++) {

            // Create a new pane with a random background color for
            // illustration
            final StackPane p = createNewPane();
            panes.add(p);

            // The addition / removal of the following line affects the
            // layout.
            p.setStyle("-fx-border-width:2px;-fx-border-color:red");
        }

        for (int r = 0; r < 2; r++) {
            final RowConstraints rc = new RowConstraints();
            rc.setPercentHeight(50);
            gridPane.getRowConstraints().add(rc);
        }
        for (int c = 0; c < 2; c++) {
            final ColumnConstraints cc = new ColumnConstraints();
            cc.setPercentWidth(50);
            gridPane.getColumnConstraints().add(cc);
        }

        for (int r = 0, i = 0; r < 2; r++) {
            for (int c = 0; c < 2; c++) {
                gridPane.add(panes.get(i++), c, r);
            }
        }
        stage.show();
    });
}

奇怪的是,如果我stage.show()在设置场景后向右移动,那么即使使用 CSS 也一切正常。

谁能帮我理解,一,这是否是预期的行为,二,为什么执行顺序stage.show()会有所不同?

谢谢!

4

1 回答 1

2

问题是什么

你的例子有点模棱两可。您无需随时设置添加到舞台的任何内容的首选大小。因此,JavaFX 平台可以在大小方面真正做任何想做的事情。设置首选百分比大小与设置首选绝对大小不同。百分比大小是相对的,所以问题变成了,相对于什么?答案尚不清楚。

至于为什么会出现这种情况:

// The addition / removal of the following line affects the
// layout.
p.setStyle("-fx-border-width:2px;-fx-border-color:red");

我不能说。我的猜测是 CSS 的使用会触发一些额外的布局逻辑,这些逻辑会在没有任何大小提示的情况下影响调整大小。

如何修复它

无论如何,解决方案只是让事情更清楚,并至少为应用程序中的某些内容指定首选大小,然后应用程序最初将调整为首选大小。

这是一个例子:

import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Starter {
    public static void main(String[] args) {
        Platform.startup(() -> {});
        Platform.runLater(() -> {
            final GridPane gridPane = new GridPane();
            final Scene scene = new Scene(gridPane);
            final Stage stage = new Stage();
            stage.setScene(scene);

            final List<StackPane> panes = new ArrayList<>();
            for (int i = 0; i < 4; i++) {

                // Create a new pane with a random background color for
                // illustration
                final StackPane p = createNewPane();
                panes.add(p);

                // The addition / removal of the following line affects the
                // layout.
                p.setStyle("-fx-border-width:2px;-fx-border-color:red");
            }

            for (int r = 0; r < 2; r++) {
                final RowConstraints rc = new RowConstraints();
                rc.setPercentHeight(50);
                gridPane.getRowConstraints().add(rc);
            }
            for (int c = 0; c < 2; c++) {
                final ColumnConstraints cc = new ColumnConstraints();
                cc.setPercentWidth(50);
                gridPane.getColumnConstraints().add(cc);
            }

            for (int r = 0, i = 0; r < 2; r++) {
                for (int c = 0; c < 2; c++) {
                    gridPane.add(panes.get(i++), c, r);
                }
            }
            stage.show();
        });
    }

    private static final Random random = new Random(42);

    private static StackPane createNewPane() {
        StackPane pane = new StackPane();

        pane.setBackground(
                new Background(
                        new BackgroundFill(
                                randomColor(), null, null
                        )
                )
        );

        pane.setPrefSize(150, 100);

        return pane;
    }

    private static Color randomColor() {
        return Color.rgb(
                random.nextInt(256),
                random.nextInt(256),
                random.nextInt(256)
        );
    }
}

解决方案的关键部分是调用:

pane.setPrefSize(150, 100);

它为放置在布局中的堆栈窗格设置首选大小。

或者,除了通过在每个 StackPane 上设置首选大小来进行自下而上的首选大小调整之外,您还可以通过在 GridPane 上设置适当的约束来从自上而下的角度完成类似的事情,例如:

 gridPane.setPrefSize(300, 200);

笔记

我建议使用 JavaFX应用程序类而不是Platform.startup()调用,除非有一个非常好的理由使用后者(在这种情况下 - 与 Swing 接口,正如您在评论中指出的那样)。

于 2018-01-26T22:26:12.433 回答