是否应该在GridPane内容上指定JavaFX CSS边框以使大小调整崩溃?

时间:2018-01-26 21:54:23

标签: java javafx javafx-9

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

Without CSS

但是,如果我在将新实例化的StackPane添加到GridPane之前添加指定边框的JavaFX CSS样式,那么事情的默认大小似乎已完全崩溃:

With 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()的执行顺序会产生影响?

谢谢!

1 个答案:

答案 0 :(得分: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);

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

或者,不是通过在每个StackPanes上设置首选大小来进行自下而上的首选大小调整,您也可以通过在GridPane上设置适当的约束来从上到下的角度完成类似的操作,例如: / p>

 gridPane.setPrefSize(300, 200);

注意

我建议使用JavaFX Application类而不是Platform.startup()调用,除非有充分的理由使用后者(在这种情况下是 - 与Swing接口,如你已在评论中注明了。)