如何在 JavaFX 的每个网格单元格中获取鼠标输入的 GridPane 行和列 ID?

How to get GridPane Row and Column IDs on Mouse Entered in each cell of Grid in JavaFX?

我正在我的应用程序中试用 JFX 拖放功能(稍后按顺序连接对象)。我找不到任何简单的方法将 ImageView/Button 拖放到窗格中的合适位置,因此我打算应用 GridPane。 GridPane 将是一个很大的 canvas,包含超过 (50x50) 个单元格。

如果我在我的代码中指定我需要通过 ImageView 拖放,比方说,(2,2) 单元格,我能够做到这一点。但是,我需要将访问权限授予我的用户。用户可以在网格中移动指针,并将 ImageView/Button 放在网格中的任何单元格中。

现在,我想找出鼠标在 GridPane 的特定单元格中输入的单元格的 rowID 和 columnID。

我在我的控制器中处理鼠标事件如下:

package sample;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.*;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{
Stage stage;

@FXML
private GridPane gridPane;

public void setStage(Stage primaryStage){
    stage = primaryStage;
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    System.out.println("initialize");
}


@FXML
private void handleMouseEntered(MouseEvent event){
    System.out.println("MouseEntered");
}

}

当进入网格面板时,我只得到一次"MouseEntered"。此外,我无法获取任何RowID和ColumnID,因此,我没有在函数中编写任何函数。

我的界面如下所示:

我想知道两件事:

[] 如何在网格面板的每个单元格中检测鼠标进入?

[] 如何找出特定单元格的行和列 ID?

提前致谢。

您可以通过调用 GridPane.getColumnIndex(node)GridPane.getRowIndex(node) 来获取值。

您没有显示您在网格窗格中放置的内容,甚至没有显示您是在 FXML 中还是在 Java 中填充它,但这里有一些基本功能。在这里,我(乏味地)在 FXML 中填充 GridPane,根据您的用例,最好在 Java 中填充它(即在控制器中)。 (这样,处理程序也会变得更干净一些。)

控制器class:

import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;


public class GridPaneTrackingController {

    @FXML
    private void mouseEntered(MouseEvent e) {
        Node source = (Node)e.getSource() ;
        Integer colIndex = GridPane.getColumnIndex(source);
        Integer rowIndex = GridPane.getRowIndex(source);
        System.out.printf("Mouse entered cell [%d, %d]%n", colIndex.intValue(), rowIndex.intValue());
    }
}

如果您不想在 FXML 中定义单元格的内容,那么您可以在控制器中定义它们。这让事情变得更清晰,因为你可以在定义它们时注册监听器:

import javafx.fxml.FXML;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;


public class GridPaneTrackingController {

    @FXML
    private GridPane grid ;

    public void initialize() {
        int numCols = 4 ;
        int numRows = 4 ;

        for (int i = 0 ; i < numCols ; i++) {
            ColumnConstraints colConstraints = new ColumnConstraints();
            colConstraints.setHgrow(Priority.SOMETIMES);
            grid.getColumnConstraints().add(colConstraints);
        }

        for (int i = 0 ; i < numRows ; i++) {
            RowConstraints rowConstraints = new RowConstraints();
            rowConstraints.setVgrow(Priority.SOMETIMES);
            grid.getRowConstraints().add(rowConstraints);
        }

        for (int i = 0 ; i < numCols ; i++) {
            for (int j = 0; j < numRows; j++) {
                addPane(i, j);
            }
        }
    }

    private void addPane(int colIndex, int rowIndex) {
        Pane pane = new Pane();
        pane.setOnMouseEntered(e -> {
            System.out.printf("Mouse enetered cell [%d, %d]%n", colIndex, rowIndex);
        });
        grid.add(pane, colIndex, rowIndex);
    }

}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.GridPane?>

<GridPane xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="GridPaneTrackingController" 
    fx:id="grid" gridLinesVisible="true">

</GridPane>

申请:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class GridPaneTrackingExample extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        GridPane root = FXMLLoader.load(getClass().getResource("GridPaneTrackingExample.fxml"));
        primaryStage.setScene(new Scene(root, 800, 800));
        primaryStage.show();
    }

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