【问题标题】:How can I draw over a GridPane of Rectangles with an Image? (JavaFX)如何使用图像绘制矩形的 GridPane? (JavaFX)
【发布时间】:2021-11-19 04:08:29
【问题描述】:

所以我试图在 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);
    }

}

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

【问题讨论】:

  • 使用Panes(或一些合适的子类)代替矩形,并向它们添加图像视图。
  • 那么我将如何获得背景矩形?
  • 使用Panes 代替矩形。
  • 嗯,我明白了。但是,似乎尝试设置窗格的颜色有点复杂,我在网上找到的示例似乎无法正常工作,执行诸如 pane.setbackground(new backgroundfill()) 之类的操作,但 IDE 只是抛出错误那
  • 那甚至无法编译。只需阅读 Java 文档。您也可以使用setStyle(…),或者设置样式类或伪类并使用外部 CSS 文件(这可能是首选方法)。

标签: java image user-interface javafx chess


【解决方案1】:

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

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

无论 Rectangle 还是 StackPane 作为您的正方形,您都可以解决问题。

使用矩形:

如果您更喜欢使用 Rectangle,您可以将 ImageView 节点包含在 Rectangle 的相同网格位置,并根据 Rectangle 调整 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));

使用 StackPane:

该方法与使用 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));
    }
}

以上两种方法中的任何一种都会产生与下面的 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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-01
    • 2016-09-22
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多