当前位置: 首页 > 知识库问答 >
问题:

JavaFX:在GridPane上更新ImageView单击

彭霄
2023-03-14

我正在使用JavaFX开发一款扫雷游戏:

我的GridPane是由ImageViews组成的,我试图找到一种方法来计算在GridPane上单击的图像的列和行索引。我目前有这个代码:

gameGrid.setOnMouseClicked(event -> //gameGrid is my GridPane
{
    Node source = (Node)event.getSource();
    int columnIndex = GridPane.getColumnIndex(source);
    System.out.println(columnIndex);
    int rowIndex = GridPane.getRowIndex(source);
    if(event.getButton()== MouseButton.PRIMARY)
    game.newRevealCell(columnIndex,rowIndex);
    else if(event.getButton()==MouseButton.SECONDARY)

    game.getGrid()[columnIndex][rowIndex].setFlagged(true);
    //game.getGrid is a 2D array containing the game cells

});

但是,方法getClonIndexgetRowIndex返回null。我做错了什么?

共有2个答案

闽高峯
2023-03-14

1感谢@trashgood提供的所有评论和答案。

但为了解决你的实际问题,我认为使用事件。getSource是问题的根本原因。事件返回的源始终是GridPane。

event.getTarget()方法将为您提供您单击的目标节点。所以我认为将其更改为getTarget()将解决您的问题。

下面是我的意思的工作演示。

更新:我错误地认为显式约束设置只能通过GridPane完成。添加方法。但是使用add/addRow/addColumn方法也会设置索引约束。

注意:如果你点击的目标节点是GridPane的直接子节点(在你的例子中),这将起作用。但是如果您的目标节点不是GridPane的直接子节点,比如StackPane有一个标签,如果您单击了该标签,就会抛出一个null异常。

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class GridPaneIndexingDemo extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 450, 450);
        stage.setScene(scene);
        stage.setTitle("GridPane");
        stage.show();

        GridPane grid = new GridPane();
        grid.setGridLinesVisible(true);
        grid.addRow(0, getPane(1), getPane(2), getPane(3));
        grid.addRow(1, getPane(4), getPane(5), getPane(6));
        grid.addRow(2, getPane(7), getPane(8), getPane(9));
        grid.setOnMouseClicked(event -> {
            Node source = (Node) event.getTarget();
            int columnIndex = GridPane.getColumnIndex(source);
            int rowIndex = GridPane.getRowIndex(source);
            System.out.println("Row : " + rowIndex + ", Col : " + columnIndex);
        });
        root.getChildren().add(grid);
    }

    private StackPane getPane(int i) {
        String[] colors = {"grey", "yellow", "blue", "pink", "brown", "white", "silver", "orange", "lightblue", "grey"};
        StackPane pane = new StackPane();
        pane.setPrefSize(150,150);
        pane.setStyle("-fx-background-color:" + colors[i] + ";-fx-border-width:2px;");
        return pane;
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}
印季
2023-03-14

从这个例子开始,下面的变化用ButtonNxN实例填充GridPane,将每个实例添加到List

每个网格按钮如何知道自己在网格中的位置?每个按钮都有自己的匿名类实例——按钮的事件处理程序——它可以访问传递给createGridButton()的行和列参数。这些参数实际上是最终的;相比之下,使用早期版本的Java的原始示例必须显式地使参数最终。

虽然这种方法获取网格中任何Node的行和列,但在该上下文中,ButtonTokgleButton可能更方便。特别是,您可以使用带有ContentDisplay.GRAPHIC_ONLY的setGrapics()来获得所需的外观。

另一方面,GridPane方法getColumnIndexgetRowIndex仅在设置时返回null,因为它们引用子级的索引约束。

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

/** @see https://stackoverflow.com/a/69429741/230513 */
public class GridButtonTest extends Application {
    
    private static final int N = 5;
    private final List<Button> list = new ArrayList<>();
    
    private Button getGridButton(int r, int c) {
        int index = r * N + c;
        return list.get(index);
    }
    
    private Button createGridButton(int row, int col) {
        Button button = new Button("r" + row + ",c" + col);
        button.setOnAction((ActionEvent event) -> {
            System.out.println(event.getSource() == getGridButton(row, col));
        });
        return button;
    }
    
    @Override
    public void start(Stage stage) {
        stage.setTitle("GridButtonTest");
        GridPane root = new GridPane();
        for (int i = 0; i < N * N; i++) {
            int row = i / N;
            int col = i % N;
            Button gb = createGridButton(row, col);
            list.add(gb);
            root.add(gb, row, col);
            GridPane.setMargin(gb, new Insets(N));
        }
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

对于使用二维数组的模型,也考虑List

import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

/** @see https://stackoverflow.com/a/69429741/230513 */
public class GridButtonTest extends Application {

    private static final int N = 5;
    private final List<List<Button>> list = new ArrayList<>();

    private Button getGridButton(int r, int c) {
        return list.get(r).get(c);
    }

    private Button createGridButton(int row, int col) {
        Button button = new Button("r" + row + ",c" + col);
        button.setOnAction((ActionEvent event) -> {
            System.out.println(event.getSource() == getGridButton(row, col));
        });
        return button;
    }

    @Override
    public void start(Stage stage) {
        stage.setTitle("GridButtonTest");
        GridPane root = new GridPane();
        for (int row = 0; row < N; row++) {
            list.add(new ArrayList<>());
            for (int col = 0; col < N; col++) {
                Button gb = createGridButton(row, col);
                list.get(row).add(gb);
                root.add(gb, row, col);
                GridPane.setMargin(gb, new Insets(N));
            }
        }
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

 类似资料:
  • 好吧,这是一个棘手的问题,这几天来一直让我抓狂... 作为users admin阶段(参见elements hierarchy)上方锚定窗格的滚动窗格的子窗格,我在UsersAdminController初始化期间添加了一个GridPane,该GridPane用于列出系统的用户(如本文所述)。当我通过user addition屏幕添加用户时,我尝试通过获取对UsersAdminController

  • 我有一个学校项目或类似的东西,我试图为用户制作一个注册面板。当用户点击注册时,这个面板会打开。它看起来像这样。 我想做的是禁用创建按钮,只有在对话框上有3个检查时才会启用。 我在对话框上使用GridPane,我在考虑返回这些单元格上的某些节点(检查是图像视图),并检查条件是否为真。然而,我不知道如何从GridPane返回节点。如果你有其他方法来解决这个问题,也没关系。 这是代码的相关部分。

  • 我是JavaFx新手,我在FXMl中创建了两个gridPane,我想用JavaFx做同样的事情。 我想创建一个扩展GridPane的类,所以当我调用我的类时,我将得到与fxml PS中相同的结果:如果您使用的是SceneBuilder,请检查网格线是否可见,以便可以看到所有GridPane谢谢

  • 我正在用JavaFX编写一个益智游戏。 您可以在单击网格后与另一个按钮进行按钮交换吗? 前任。我想在按下按钮1后交换按钮1和9。我认为应该有可能改变网格窗格的位置。 当我点击按钮4时,它与按钮9互换。 有没有办法做到这一点? 这是我的代码:

  • 我打算再试一次。。。我是Scenebuilder的新手,我正在尝试为我的项目创建一个照片库!我已经添加了我想要的,那就是一个图像视图,其中的图像是从FileChooser中选择的。。。但是现在我想得到一个建议,如何保存这个,并在每次按下addPhoto按钮时创建一个新的,而不是覆盖我在ImageView中已经有的。以下是我的addPhoto按钮代码: FXML代码:

  • 主要内容:示例,示例2GridPane通常用于布局:第一列上的只读标签的输入表单和第二列上的输入字段。 GridPane可以在行,列或单元格级别指定约束。 例如,我们可以设置包含输入文本字段的第二列,以在窗口调整大小时调整大小。 示例 以下代码演示使用GridPane布局的简单表单应用程序。它有以下布局。 完整的代码实现如下所示 - 上面的代码生成以下结果。 示例2 以下是一个实现登录窗口的代码 - 上面的代码生成以下