如何使用图像在矩形 GridPane 上绘制?(JavaFX)

Dae*_*guy 3 java user-interface chess javafx image

所以我试图用Java显示一个棋盘。到目前为止,我可以正确绘制一堆矩形并为其着色,并正确调整窗口和矩形的大小。但是,现在我想在这些矩形的顶部添加一个国际象棋棋子的图像,但我不知道如何继续。

我为棋子创建了一个 png 的图像视图,但是当我尝试将其添加到网格窗格中(就像我对矩形所做的那样)时,它给了我一个重复的子错误。

这是迄今为止有效的代码

package test3;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.image.*;
/**
 *

 */
public class Test3 extends Application {
    GridPane root = new GridPane();
    final int size = 8;
    ImageView pawn = new ImageView("file:pawn.png");
    @Override
    public void start(Stage primaryStage) throws Exception {
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                Rectangle square = new Rectangle();
                Color color;
                if ((row + col) % 2 == 0) { 
                    color = Color.CHOCOLATE;
                }
                else {
                    color = Color.ANTIQUEWHITE;
                }
                square.setFill(color);
                
                root.add(square, col, row);
                square.widthProperty().bind(root.widthProperty().divide(size));
                square.heightProperty().bind(root.heightProperty().divide(size));
                
            }
        }
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

创建棋子的图像视图并将其绘制在矩形顶部(就像棋盘上的棋子一样)的最佳方法是什么?我已经有一个文件,比如 pawn.png,我可以制作它的图像视图,但是每当我尝试将图像视图添加到我绘制矩形的网格窗格时,它都会出错。我不知道该怎么办。我尝试使用第二个网格窗格,在其中仅添加图像,但这也会导致重复的子错误。

Sai*_*dem 5

(我的一些观点可能已经在评论中解决了)

您需要解决的第一件事是为每个方块创建单独的 ImageView 节点,因为您无法复制场景图中的节点。

无论您的正方形是矩形还是 StackPane,都可以解决该问题。

使用矩形:

如果您更喜欢使用矩形,则可以将 ImageView 节点包含在矩形的同一网格位置中,并根据矩形调整 ImageView 节点的宽度/高度。

ImageView pawn = new ImageView(getClass().getResource("pawn.png").toExternalForm());
root.add(pawn, col, row);
pawn.fitWidthProperty().bind(square.widthProperty().subtract(2));
pawn.fitHeightProperty().bind(square.heightProperty().subtract(2));
Run Code Online (Sandbox Code Playgroud)

使用堆栈窗格:

该方法与使用 Rectangle 几乎相同,但您将把 ImageView 节点放置在 StackPane 而不是 GridPane 中。使用 StackPane 的另一个优点是 ImageView 将自动以您的正方形为中心。您还可以包含一个可选代码来调整图像大小以适合正方形。

Background dark = new Background(new BackgroundFill(Color.CHOCOLATE, CornerRadii.EMPTY, Insets.EMPTY));
Background light = new Background(new BackgroundFill(Color.ANTIQUEWHITE, CornerRadii.EMPTY, Insets.EMPTY));
for (int row = 0; row < size; row++) {
    for (int col = 0; col < size; col++) {
        ImageView pawn = new ImageView(getClass().getResource("pawn.png").toExternalForm());
        StackPane square = new StackPane(pawn);
        square.setBackground((row + col) % 2 == 0?dark:light);
        root.add(square, col, row);
        square.prefWidthProperty().bind(root.widthProperty().divide(size));
        square.prefHeightProperty().bind(root.heightProperty().divide(size));

        // Comment the below two lines if you don't want the images to resize.
        pawn.fitWidthProperty().bind(square.widthProperty().subtract(2));
        pawn.fitHeightProperty().bind(square.heightProperty().subtract(2));
    }
}
Run Code Online (Sandbox Code Playgroud)

上述两种方法都会产生与下面的 gif 相同的结果。工作演示如下:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class ChessBoardDemo extends Application {
    GridPane root = new GridPane();
    final int size = 8;

    @Override
    public void start(Stage primaryStage) throws Exception {
        yourApproach();
        // usingPane(); 
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.setTitle("ChessBoard");
        primaryStage.show();
    }

    private void usingPane() {
        Background dark = new Background(new BackgroundFill(Color.CHOCOLATE, CornerRadii.EMPTY, Insets.EMPTY));
        Background light = new Background(new BackgroundFill(Color.ANTIQUEWHITE, CornerRadii.EMPTY, Insets.EMPTY));
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                ImageView pawn = new ImageView(getClass().getResource("pawn.png").toExternalForm());
                StackPane square = new StackPane(pawn);
                square.setBackground((row + col) % 2 == 0 ? dark : light);
                root.add(square, col, row);
                square.prefWidthProperty().bind(root.widthProperty().divide(size));
                square.prefHeightProperty().bind(root.heightProperty().divide(size));

                // Comment the below two lines if you don't want the images to resize.
                pawn.fitWidthProperty().bind(square.widthProperty().subtract(2));
                pawn.fitHeightProperty().bind(square.heightProperty().subtract(2));
            }
        }
    }

    private void yourApproach() {
        for (int row = 0; row < size; row++) {
            for (int col = 0; col < size; col++) {
                Rectangle square = new Rectangle();
                square.setFill((row + col) % 2 == 0 ? Color.CHOCOLATE : Color.ANTIQUEWHITE);

                root.add(square, col, row);
                square.widthProperty().bind(root.widthProperty().divide(size));
                square.heightProperty().bind(root.heightProperty().divide(size));

                ImageView pawn = new ImageView(getClass().getResource("pawn.png").toExternalForm());
                root.add(pawn, col, row);
                pawn.fitWidthProperty().bind(square.widthProperty().subtract(2));
                pawn.fitHeightProperty().bind(square.heightProperty().subtract(2));
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述