web-dev-qa-db-ja.com

GridPaneJavaFXに境界線を追加する

GridPaneを使用してJavaFXでボードゲームを作成しています。

グリッドの各グリッド(セル)に配置できる7つの異なるアニメーションがあります。

最初、グリッドは次のようになります

empty gridpane

アニメーションの挿入をプログラミングする前に、単純な円を追加してテストしました。そしてそれはこのように見えます

gridpane with subscenes

enter image description here

追加されたノードは、TimeLineアニメーションを含むSubScenesです。各セルサイズは40x40で、SubSceneサイズも40x40です。

サブシーンを追加すると、グリッドペインの境界線の上に表示され、見栄えが悪くなります。

ノードがグリッド線の下に追加されるようにするにはどうすればよいですか?つまり、グリッド線はノードの上にあります。

GridPaneでそれが不可能な場合、他に使用できるものはありますか?

ゲームのために実行するクラス

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

アニメーションを含むクラス、ここでは円を作成しています

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;
    }
}
5
Jeet Parekh

setGridLinesVisible(true)を使用しないでください: documentation は、これがデバッグ専用であることを明示的に示しています。

代わりに、すべてのグリッドセル(空のセルも含む)にペインを配置し、境界線が表示されるようにペインのスタイルを設定します。 (これにより、境界線を非常に注意深く制御できるため、二重境界線などを回避できます。)次に、各ペインにコンテンツを追加します。マウスリスナーをペインに登録することもできます。つまり、クリックされたセルを特定するために醜い計算を行う必要はありません。

任意の領域に境界線を適用するための推奨される方法は、CSSと「ネストされた背景」アプローチを使用することです。このアプローチでは、領域に2つ(またはそれ以上)の背景の塗りつぶしを異なる挿入図で描画し、境界線の外観を与えます。したがって、たとえば:

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

最初にはめ込みのない黒い背景を描画し、次にその上にすべての側面に1ピクセルのはめ込みのある白い背景を描画し、幅1ピクセルの黒い境界線の外観を与えます。これは直感に反しているように見えるかもしれませんが、これのパフォーマンスは(伝えられるところでは)境界を直接指定するよりも優れています。 each塗りつぶしのインセットに、4つの値のシーケンスを指定することもできます。これは、上、右、下、および左のインセットとして解釈されます。 、それぞれ。そう

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

このアプローチは、コメントで@James_Dによって承認されています。

1ピクセル幅のHとVのギャップを追加し、グリッドペインの背景色を「輝かせる」だけです。

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

グリッドペインの背景色が複数のピクセルの外側から広がっている場合(親がそれ自体よりも大きい場合に発生します)、グリッドをGroupでラップするだけです。

3
Mordechai