向 GridPane JavaFX 添加边框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32892646/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:00:07  来源:igfitidea点击:

Adding borders to GridPane JavaFX

javaanimationjavafxjavafx-2javafx-8

提问by Jeet Parekh

I am creating a board game in JavaFX using GridPane.

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

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

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

Initially the grid looks like this

最初的网格看起来像这样

empty gridpane

空网格

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

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

gridpane with subscenes

带有子场景的网格

enter image description here

在此处输入图片说明

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

添加的节点是包含时间线动画的子场景。每个单元格大小为 40x40,SubScene 大小也是 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.

我该怎么做才能将节点添加到网格线下方?即网格线在节点的顶部。

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

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

class which i execute for the game

我为游戏执行的课程

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;
    }
}

采纳答案by James_D

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

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

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.

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

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:

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

-fx-background-fill: black, white ;
-fx-background-insets: 0, 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 eachfill, which are interpreted as the insets on the top, right, bottom, and left, respectively. So

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

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

has the effect of a black border on the right and bottom, etc.

在右侧和底部等处具有黑色边框的效果。

I'm also not sure SubSceneis 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 Groupdirectly to each cell (you could probably just add the circle, depending on exactly what you need...).

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

Something like:

就像是:

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);
    }
}

and the css:

和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 ;
}

回答by Mordechai

Simply add an H and V gap of one pixel width and let the grid pane's background color "shine" through:

只需添加一个像素宽度的 H 和 V 间隙,让网格窗格的背景颜色“发光”:

.my-grid-pane {
    -fx-background-color: lightgray;
    -fx-vgap: 1;
    -fx-hgap: 1;
    -fx-padding: 1;
}

If the grid pane's background color spreads from outside more than one pixel (will happen if its parent is larger than itself), just wrap the grid in a Group!

如果网格窗格的背景颜色从外部扩散超过一个像素(如果其父级大于自身就会发生这种情况),只需将网格包裹在Group!