【问题标题】:BorderPane not showing other pane except for center JavafxBorderPane 不显示除中心 Javafx 之外的其他窗格
【发布时间】:2021-11-07 20:41:47
【问题描述】:

我这里有一段代码,它有一个边框窗格作为父窗格和两个其他窗格,一个是扫雷游戏,另一个是黑色背景的空窗格,扫雷游戏设置在边框窗格和空窗格设置为底部。现在当我运行代码时,它只会显示扫雷游戏而不是空窗格(可以在图像中看到)。如何让它在边框窗格底部显示空窗格?

(截至目前的布局)

package project;

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

import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class MinesweeperApp extends Application {

    private static final int TILE_SIZE = 40;
    private static final int W = 800;
    private static final int H = 800;

    private static final int X_TILES = W / TILE_SIZE;
    private static final int Y_TILES = H / TILE_SIZE;

    private Tile[][] grid = new Tile[X_TILES][Y_TILES];
//    private ArrayList[][] grid = new ArrayList[X_TILES][Y_TILES];
    private Scene scene;

    private Parent createContent() {
        BorderPane root = new BorderPane();
        Pane middlepane = new Pane();
        Pane lowerPane = new Pane();
        

        lowerPane.setStyle("-fx-background-color: black;");
        root.setTop(lowerPane);
        root.setBottom(middlepane);
        middlepane.setPrefSize(W, H);

        for (int y = 0; y < Y_TILES; y++) {
            for (int x = 0; x < X_TILES; x++) {
                Tile tile = new Tile(x, y, Math.random() < 0.2);

                grid[x][y] = tile;
                middlepane.getChildren().add(tile);
            }
        }

        for (int y = 0; y < Y_TILES; y++) {
            for (int x = 0; x < X_TILES; x++) {
                Tile tile = grid[x][y];

                if (tile.hasBomb)
                    continue;

                long bombs = getNeighbors(tile).stream().filter(t -> t.hasBomb).count();

                if (bombs > 0)
                    tile.text.setText(String.valueOf(bombs));
            }
        }

        return root;
    }

    private List<Tile> getNeighbors(Tile tile) {
        List<Tile> neighbors = new ArrayList<>();

        // ttt
        // tXt
        // ttt

        int[] points = new int[] {
                -1, -1,
                -1, 0,
                -1, 1,
                0, -1,
                0, 1,
                1, -1,
                1, 0,
                1, 1
        };

        for (int i = 0; i < points.length; i++) {
            int dx = points[i];
            int dy = points[++i];

            int newX = tile.x + dx;
            int newY = tile.y + dy;

            if (newX >= 0 && newX < X_TILES
                    && newY >= 0 && newY < Y_TILES) {
                neighbors.add(grid[newX][newY]);
            }
        }

        return neighbors;
    }

    private class Tile extends StackPane {
        private int x, y;
        private boolean hasBomb;
        private boolean isOpen = false;

        private Rectangle border = new Rectangle(TILE_SIZE - 2, TILE_SIZE - 2);
        private Text text = new Text();

        public Tile(int x, int y, boolean hasBomb) {
            this.x = x;
            this.y = y;
            this.hasBomb = hasBomb;

            border.setStroke(null);
            border.setFill(Color.NAVY);

            text.setFont(Font.font(18));
            text.setText(hasBomb ? "X" : "");
            text.setVisible(false);

            getChildren().addAll(border, text);

            setTranslateX(x * TILE_SIZE);
            setTranslateY(y * TILE_SIZE);

            setOnMouseClicked(e -> open());
        }

        public void open() {
            System.out.println("clicked");
            System.out.println("x: " + this.x + " " + "y: " + this.y);
            if (isOpen){
                return;
            }



            if (hasBomb) {
                System.out.println("Game Over");
                scene.setRoot(createContent());
                return;
            }

            isOpen = true;
            text.setVisible(true);
            border.setFill(Color.RED);

            if (text.getText().isEmpty()) {
                getNeighbors(this).forEach(Tile::open);
            }
        }
    }

    @Override
    public void start(Stage stage) throws Exception {
        scene = new Scene(createContent());
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {

        launch(args);
    }
}

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    没有孩子,一个空的Pane 的宽度和高度为零。尝试在顶部和底部添加非空内容,看看效果:

    root.setTop(new Label("top"));
    root.setCenter(middlepane);
    root.setBottom(new Label("bottom"));
    


    顺便说一句,您原来的root.setBottom(middlepane) 可能会产生误导。

    【讨论】:

      【解决方案2】:

      设置约束

      在窗格上设置大小限制以“查看”没有内容的窗格。

      这将使窗格占用布局中的空间。

      要使应用按照您的意愿运行,请配置窗格的:

      • 最小宽度或高度,或
      • 首选宽度或高度,或
      • 这些的任意组合。

      例如,为边框窗格中的顶部窗格设置最小高度:

      BorderPane borderPane = new BorderPane();
      
      Pane top = new Pane();
      top.setMinHeight(15);
      borderPane.setTop(top); 
      

      隐藏内容

      或者您可以将一些内容放在窗格中,使其在需要时不可见,同时仍保留显示它所需的空间。

      例如:

      Label header = new Label("header");
      header.setVisible(false);
      Pane top = new Pane(header);
      borderPane.setTop(top);
      

      这是因为场景图中不可见的东西仍然占用布局空间,即使它们没有显示出来,除非你也调用setManaged(false)

      对于标签的特定情况,您不需要可见性设置,您可以将标签设置为空字符串,它仍然会占用空间,即使不会显示任何内容。

      对于我自己,我尽量避免调整大小提示,所以我会使用一个空标签。或者,为更复杂的窗格设置可见性。这样我就让布局引擎计算出适当的空间量来保留。

      内容间距

      这不适用于边框窗格的情况,但对于 HBox 和 VBox 等其他布局,您可能希望将节点一直推到布局的右侧或底部。您可以通过在最后一个节点之前添加一个空窗格并在窗格上设置布局约束来做到这一点,如下所示:

      HBox.setHgrow(spacer, Priority.ALWAYS);
      

      此技术在以下答案中得到了更多解释:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-25
        相关资源
        最近更新 更多