向 GridPane JavaFX 添加边框 [英] Adding borders to GridPane JavaFX

查看:63
本文介绍了向 GridPane JavaFX 添加边框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 GridPane 在 JavaFX 中创建棋盘游戏.

I am creating a board game in JavaFX using GridPane.

有 7 种不同的动画可以放置在网格的每个网格(单元格)中.

There are 7 different animations which could be placed in each grid (cell) of the grid.

最初的网格看起来像这样

Initially the grid looks like this

在编写我的动画插入之前,我测试了向它添加一个简单的圆圈.它看起来像这样

I tested adding a simple circle to it before programming my animation insertions. And it looks like this

添加的节点是包含时间线动画的子场景.每个单元格大小为 40x40,SubScene 大小也为 40x40.

The nodes added are SubScenes which include TimeLine animation. Each cell size is 40x40 and the SubScene size is also 40x40.

添加子场景时,位于网格窗格边界线的顶部,看起来不太好.

The subscenes when added, get on top of the gridpane border lines and it doesn't look good.

如何将节点添加到网格线下方?即网格线位于节点的顶部.

What can I do so that the nodes are added below the grid lines? i.e. the gridlines are on top of the nodes.

如果无法使用 GridPane,还有什么我可以使用的吗?

If it is not possible with GridPane, is there anything else I can use?

我为游戏执行的类

class Game {
    static GridPane grid;
    public void start(final Stage stage) throws Exception {
        int rows = 5;
        int columns = 5;

        stage.setTitle("Enjoy your game");
        grid = new GridPane();
        for(int i = 0; i < columns; i++) {
            ColumnConstraints column = new ColumnConstraints(40);
            grid.getColumnConstraints().add(column);
        }

        for(int i = 0; i < rows; i++) {
            RowConstraints row = new RowConstraints(40);
            grid.getRowConstraints().add(row);
        }

        grid.setOnMouseReleased(new EventHandler<MouseEvent> () {
            public void handle(MouseEvent me) {
                grid.add(Anims.getAnim(1), (int)((me.getSceneX() - (me.getSceneX() % 40)) / 40), (int)((me.getSceneY() - (me.getSceneY() % 40)) / 40)); //here the getAnim argument could be between 1-7
            }
        });

        grid.setStyle("-fx-background-color: white; -fx-grid-lines-visible: true");
        Scene scene = new Scene(grid, (columns * 40) + 100, (rows * 40) + 100, Color.WHITE);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(final String[] arguments) {
        Application.launch(arguments);
    }
}

包含动画的类,这里我只是创建一个圆

class which contains animations, here I am just creating a circle

public class Anims {

    public static SubScene getAnim(final int number) throws Exception {
        Circle circle = new Circle(20, 20f, 7);
        circle.setFill(Color.RED);
        Group group = new Group();
        group.getChildren().add(circle);
        SubScene scene = new SubScene(group, 40, 40);
        scene.setFill(Color.WHITE);
        return scene;
    }
}

推荐答案

不要使用 setGridLinesVisible(true):文档 明确指出这仅用于调试.

Don't use setGridLinesVisible(true): the documentation explicitly states this is for debug only.

相反,在所有网格单元格(甚至是空单元格)中放置一个窗格,并设置窗格样式以便您看到边框.(这使您有机会非常小心地控制边框,从而避免出现双边框等)然后将内容添加到每个窗格中.您还可以在窗格中注册鼠标侦听器,这意味着您无需进行丑陋的数学运算即可确定单击了哪个单元格.

Instead, place a pane in all the grid cells (even the empty ones), and style the pane so you see the borders. (This gives you the opportunity to control the borders very carefully, so you can avoid double borders, etc.) Then add the content to each pane. You can also register the mouse listeners with the pane, which means you don't have to do the ugly math to figure out which cell was clicked.

将边框应用于任何区域的推荐方法是使用 CSS 和嵌套背景"方法.在这种方法中,您在该区域上绘制两个(或更多)背景填充,使用不同的插图,呈现边框的外观.例如:

The recommended way to apply a border to any region is to use CSS and a "nested background" approach. In this approach, you draw two (or more) background fills on the region, with different insets, giving the appearance of a border. So for example:

-fx-background-fill: black, white ;
-fx-background-insets: 0, 1 ;

将首先绘制一个没有插图的黑色背景,然后在其上绘制一个白色背景,在所有边上都有 1 个像素的插图,呈现宽度为 1 个像素的黑色边框的外观.虽然这似乎违反直觉,但其性能(据称)比直接指定边框要好.您还可以为 每个 填充的插图指定四个值的序列,它们分别被解释为顶部、右侧、底部和左侧的插图.所以

will first draw a black background with no insets, and then over that will draw a white background with insets of 1 pixel on all sides, giving the appearance of a black border of width 1 pixel. While this may seem counter-intuitive, the performance of this is (allegedly) better than specifying border directly. You can also specify a sequence of four values for the insets for each fill, which are interpreted as the insets on the top, right, bottom, and left, respectively. So

-fx-background-fill: black, white ;
-fx-background-insets: 0, 0 1 1 0 ;

具有左右黑边等效果

我也不确定 SubScene 是否是您真正想要的,除非您打算将不同的相机连接到每个单元格.如果您确实需要一个子场景,请将填充设置为透明以避免绘制超出单元格的边缘.您可以将 Group 直接添加到每个单元格中(您可能只添加圆圈,具体取决于您的需要......).

I'm also not sure SubScene is what you really want, unless you are intending attaching different cameras to each cell. If you really need a subscene, make the fill transparent to avoid drawing over the edges of the cell. You could just add the Group directly to each cell (you could probably just add the circle, depending on exactly what you need...).

类似于:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.RowConstraints;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class Game2 extends Application{
    @Override
    public void start(final Stage stage) throws Exception {
        int rows = 5;
        int columns = 5;

        stage.setTitle("Enjoy your game");

        GridPane grid = new GridPane();
        grid.getStyleClass().add("game-grid");

        for(int i = 0; i < columns; i++) {
            ColumnConstraints column = new ColumnConstraints(40);
            grid.getColumnConstraints().add(column);
        }

        for(int i = 0; i < rows; i++) {
            RowConstraints row = new RowConstraints(40);
            grid.getRowConstraints().add(row);
        }

        for (int i = 0; i < columns; i++) {
            for (int j = 0; j < rows; j++) {
                Pane pane = new Pane();
                pane.setOnMouseReleased(e -> {
                    pane.getChildren().add(Anims.getAtoms(1));
                });
                pane.getStyleClass().add("game-grid-cell");
                if (i == 0) {
                    pane.getStyleClass().add("first-column");
                }
                if (j == 0) {
                    pane.getStyleClass().add("first-row");
                }
                grid.add(pane, i, j);
            }
        }


        Scene scene = new Scene(grid, (columns * 40) + 100, (rows * 40) + 100, Color.WHITE);
        scene.getStylesheets().add("game.css");
        stage.setScene(scene);
        stage.show();
    }

    public static class Anims {

        public static Node getAtoms(final int number) {
            Circle circle = new Circle(20, 20f, 7);
            circle.setFill(Color.RED);
            Group group = new Group();
            group.getChildren().add(circle);
//            SubScene scene = new SubScene(group, 40, 40);
//            scene.setFill(Color.TRANSPARENT);
            return group;
        }
    }

    public static void main(final String[] arguments) {
        Application.launch(arguments);
    }
}

和CSS:

.game-grid {
    -fx-background-color: white ;
    -fx-padding: 10 ;
}
.game-grid-cell {
    -fx-background-color: black, white ;
    -fx-background-insets: 0, 0 1 1 0 ;
}
.game-grid-cell.first-row {
    -fx-background-insets: 0, 1 1 1 0 ;
}
.game-grid-cell.first-column {
    -fx-background-insets: 0, 0 1 1 1 ;
}
.game-grid-cell.first-row.first-column {
    -fx-background-insets: 0, 1 ;
}

这篇关于向 GridPane JavaFX 添加边框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆