【问题标题】:Is specifying JavaFX CSS borders on GridPane contents supposed to collapse the sizing?在 GridPane 内容上指定 JavaFX CSS 边框是否应该折叠大小?
【发布时间】:2018-01-26 21:54:23
【问题描述】:

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

但是,如果我在将新实例化的 StackPane 添加到 GridPane 之前添加一个指定边框的 JavaFX 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() 的执行顺序会有所不同?

谢谢!

【问题讨论】:

  • Platform.startUp() 方法是 Java 9 的新方法。我以前没见过。调用这个方法是很不寻常的,通常你会扩展Application
  • @jewelsea 我必须做一个明确的Platform.startUp(),因为这个问题是在一个混合了遗留Swing 元素和更新的FX 元素的应用程序的上下文中出现的。应用程序本身在 Swing 环境中启动(目前)。

标签: java javafx javafx-9


【解决方案1】:

问题是什么

你的例子有点模棱两可。您无需随时设置添加到舞台的任何内容的首选大小。因此,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 Application 类而不是 Platform.startup() 调用,除非有充分的理由使用后者(在这种情况下 - 与 Swing 接口,正如您在评论中指出的那样)。

【讨论】:

    猜你喜欢
    • 2015-01-27
    • 2015-12-29
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多