向 GridPane JavaFX 添加边框
Adding borders to GridPane JavaFX
我正在使用 GridPane 在 JavaFX 中创建棋盘游戏。
网格的每个网格(单元格)中可以放置 7 种不同的动画。
最初网格看起来像这样
我测试了在编写动画插入之前向其中添加一个简单的圆圈。它看起来像这样
添加的节点是包含TimeLine动画的SubScenes。每个cell大小为40x40,SubScene大小也是40x40.
添加的子场景在网格窗格边框线的顶部,看起来不太好。
我该怎么做才能将节点添加到网格线下方?即网格线位于节点之上。
如果 GridPane 无法使用,还有什么我可以使用的吗?
class 我为游戏执行的
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里面有动画,这里我只是创建一个圆圈
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)
:documentation 明确指出这仅用于调试。
相反,在所有网格单元格(甚至是空单元格)中放置一个窗格,并设置窗格样式以便您看到边框。 (这让您有机会非常仔细地控制边框,这样您就可以避免出现双边框等情况。)然后将内容添加到每个窗格中。您还可以在窗格中注册鼠标侦听器,这意味着您不必进行难看的数学运算来确定单击了哪个单元格。
向任何区域应用边框的推荐方法是使用 CSS 和 "nested background" 方法。在这种方法中,您在区域上绘制两个(或更多)背景填充,具有不同的插图,呈现出边框的外观。例如:
-fx-background-fill: black, white ;
-fx-background-insets: 0, 1 ;
将首先绘制一个没有插图的黑色背景,然后在其上方绘制一个白色背景,所有边都有 1 个像素的插图,呈现出宽度为 1 像素的黑色边框。虽然这似乎违反直觉,但它的性能(据称)比直接指定边界要好。您还可以为 each 填充的插图指定一个包含四个值的序列,它们分别被解释为顶部、右侧、底部和左侧的插图。所以
-fx-background-fill: black, white ;
-fx-background-insets: 0, 0 1 1 0 ;
有右下黑边等效果
我也不确定 SubScene
是您真正想要的,除非您打算为每个单元安装不同的相机。如果你真的需要一个子场景,让填充透明以避免绘制在单元格的边缘。您可以直接将 Group
添加到每个单元格(您可能只添加圆圈,具体取决于您的需要...)。
类似于:
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 ;
}
只需添加一个像素宽度的 H 和 V 间隙,并让网格窗格的背景色 "shine" 通过:
.my-grid-pane {
-fx-background-color: lightgray;
-fx-vgap: 1;
-fx-hgap: 1;
-fx-padding: 1;
}
如果网格窗格的背景颜色从外部扩散超过一个像素(如果其父项大于自身,就会发生),只需将网格包裹在 Group
!
中
我为回复而不是评论道歉,没有足够的声誉。
奇怪的是,@James_D 的回复对我没有帮助;当 window 调整大小时,单元格边框随机改变宽度,相互重叠。
帮助解决了问题,因此通过稍微更改@James_D 给出的代码(仅 .css 文件),我们得到:
.classes-grid {
-fx-background-color: white ;
-fx-padding: 10 ;
}
.classes-grid-cell {
-fx-border-color: dimgray;
-fx-border-width: 0 1 1 0;
-fx-background-color: transparent;
}
.classes-grid-cell.first-row {
-fx-border-width: 1 1 1 0 ;
}
.classes-grid-cell.first-column {
-fx-border-width: 0 1 1 1 ;
}
.classes-grid-cell.first-row.first-column {
-fx-border-width: 1 ;
}
与 Mordechai 的回答相同。但是如果你想通过 JavaFX 代码设置这些东西,而不是 CSS 样式表。然后你可以这样做:
设置 Hgap 和 Vgap: gridpane.setHgap(1)
和 gridpane.setVgap(1)
设置背景颜色: gridpane.setBackground(new Background(new BackgroundFill(Color.rgb(0,0,0), new CornerRadii(2.5), new Insets(-1.0))))
(CornerRadii和Insets值取决于您的选择,背景颜色由rgb值决定)
我正在使用 GridPane 在 JavaFX 中创建棋盘游戏。
网格的每个网格(单元格)中可以放置 7 种不同的动画。
最初网格看起来像这样
我测试了在编写动画插入之前向其中添加一个简单的圆圈。它看起来像这样
添加的节点是包含TimeLine动画的SubScenes。每个cell大小为40x40,SubScene大小也是40x40.
添加的子场景在网格窗格边框线的顶部,看起来不太好。
我该怎么做才能将节点添加到网格线下方?即网格线位于节点之上。
如果 GridPane 无法使用,还有什么我可以使用的吗?
class 我为游戏执行的
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里面有动画,这里我只是创建一个圆圈
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)
:documentation 明确指出这仅用于调试。
相反,在所有网格单元格(甚至是空单元格)中放置一个窗格,并设置窗格样式以便您看到边框。 (这让您有机会非常仔细地控制边框,这样您就可以避免出现双边框等情况。)然后将内容添加到每个窗格中。您还可以在窗格中注册鼠标侦听器,这意味着您不必进行难看的数学运算来确定单击了哪个单元格。
向任何区域应用边框的推荐方法是使用 CSS 和 "nested background" 方法。在这种方法中,您在区域上绘制两个(或更多)背景填充,具有不同的插图,呈现出边框的外观。例如:
-fx-background-fill: black, white ;
-fx-background-insets: 0, 1 ;
将首先绘制一个没有插图的黑色背景,然后在其上方绘制一个白色背景,所有边都有 1 个像素的插图,呈现出宽度为 1 像素的黑色边框。虽然这似乎违反直觉,但它的性能(据称)比直接指定边界要好。您还可以为 each 填充的插图指定一个包含四个值的序列,它们分别被解释为顶部、右侧、底部和左侧的插图。所以
-fx-background-fill: black, white ;
-fx-background-insets: 0, 0 1 1 0 ;
有右下黑边等效果
我也不确定 SubScene
是您真正想要的,除非您打算为每个单元安装不同的相机。如果你真的需要一个子场景,让填充透明以避免绘制在单元格的边缘。您可以直接将 Group
添加到每个单元格(您可能只添加圆圈,具体取决于您的需要...)。
类似于:
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 ;
}
只需添加一个像素宽度的 H 和 V 间隙,并让网格窗格的背景色 "shine" 通过:
.my-grid-pane {
-fx-background-color: lightgray;
-fx-vgap: 1;
-fx-hgap: 1;
-fx-padding: 1;
}
如果网格窗格的背景颜色从外部扩散超过一个像素(如果其父项大于自身,就会发生),只需将网格包裹在 Group
!
我为回复而不是评论道歉,没有足够的声誉。
奇怪的是,@James_D 的回复对我没有帮助;当 window 调整大小时,单元格边框随机改变宽度,相互重叠。
.classes-grid {
-fx-background-color: white ;
-fx-padding: 10 ;
}
.classes-grid-cell {
-fx-border-color: dimgray;
-fx-border-width: 0 1 1 0;
-fx-background-color: transparent;
}
.classes-grid-cell.first-row {
-fx-border-width: 1 1 1 0 ;
}
.classes-grid-cell.first-column {
-fx-border-width: 0 1 1 1 ;
}
.classes-grid-cell.first-row.first-column {
-fx-border-width: 1 ;
}
与 Mordechai 的回答相同。但是如果你想通过 JavaFX 代码设置这些东西,而不是 CSS 样式表。然后你可以这样做:
设置 Hgap 和 Vgap: gridpane.setHgap(1)
和 gridpane.setVgap(1)
设置背景颜色: gridpane.setBackground(new Background(new BackgroundFill(Color.rgb(0,0,0), new CornerRadii(2.5), new Insets(-1.0))))
(CornerRadii和Insets值取决于您的选择,背景颜色由rgb值决定)