How to get GridPane Row and Column IDs on Mouse En

2019-01-12 12:37发布

问题:

I am trying out JFX Drag and Drop feature in my application (later connecting the objects in a sequence). I could not find any easy way to drag and drop my ImageView/Button at suitable position in my pane, hence I am planning to apply use of GridPane. The GridPane would be a large canvas with more than (50x50) cells.

If I specify in my code that I need to drag and drop by ImageView at, let's say, (2,2) cell, I am able to do it. But, I need to give that access to my user. User could move the pointer in grid and would drop the ImageView/Button at any cell in the grid.

Now, I would like to find out rowID and columnID of the cell on mouse entered in a particular cell of the GridPane.

I am handling mouse event in my Controller as follows:

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

}

When enters in the gridpane, I get "MouseEntered" only once. Besides, I am not able to get any RowID and ColumnID, hence, I have not written any function in the function.

My interface looks like following:

I would like to know two things:

[] How to detect mouse entry in each cell of the gridpane?

[] How to find out row and column IDs of the particular cell?

Thanks in advance.

回答1:

You can get the values by calling GridPane.getColumnIndex(node) and GridPane.getRowIndex(node).

You haven't shown what you're putting in the grid pane, and even whether you are populating it in FXML or in Java, but here's some basic functionality. Here I (tediously) populate the GridPane in FXML, it might be better to populate it in Java (i.e. in the controller), depending on your use case. (That way, the handler gets a bit cleaner too.)

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

If you don't want to define the contents of the cells in FXML, then you can just define them in the controller. That makes things cleaner, as you can just register the listener when you define them:

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>

Application:

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