如何单击GridPane单元并让它执行操作? [英] How can I click a GridPane Cell and have it perform an action?

查看:137
本文介绍了如何单击GridPane单元并让它执行操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是JavaFX的新手(就此而言是Java),我希望能够单击一个GridPane并让它在侧面板(或此时的控制台)中显示我的房间属性。我设法设置了一个鼠标事件,但我认为它不适合这项工作。当我点击网格中的任何地方时,它返回null并且不会给我单元格坐标(也许有更好或更有用的信息来收集这里?)。

I'm new to JavaFX (Java for that matter) and I want to be able to click a GridPane and have it display my room attributes in a side-panel(or to console at this point). I've managed to setup a mouse event but I don't think it's the right tool for the job. When I click anywhere in the grid, it returns "null" and won't give me the cell coordinates(maybe there's better or more useful info to gather here?).

我也在使用Scene Builder。

I'm using Scene Builder as well.

控制器类

import Data.Area;
import Model.Grid;
import Model.TileSet;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import java.io.IOException;
import java.io.InputStream;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class Controller {
    InputStream rinput = getClass().getResourceAsStream("/red.png");
    Image red = new Image(rinput);
    ImageView redimg = new ImageView(red);


    InputStream binput = getClass().getResourceAsStream("/black.png");
    Image black = new Image(binput);

    InputStream pinput = getClass().getResourceAsStream("/pink.png");
    Image pink = new Image(binput);

    @FXML
    public GridPane gridmane;


    public void genSmall(ActionEvent actionEvent) throws IOException {

        Grid grid = new Grid(new Area(40, 40));
        grid.getPathfinder().shufflePartitions();
        grid.getPathfinder().fillPartitions();
        grid.getPathfinder().generateHallways();
        grid.getPathfinder().placeWalls();
        importGrid(gridmane, grid);

        gridmane.getScene().getWindow().sizeToScene();
    }

    public void genMed(ActionEvent actionEvent) throws IOException {

        Grid grid = new Grid(new Area(60, 60));
        grid.getPathfinder().shufflePartitions();
        grid.getPathfinder().fillPartitions();
        grid.getPathfinder().generateHallways();
        grid.getPathfinder().placeWalls();
        gridmane.getScene().getWindow().sizeToScene();
        gridmane.getScene().getWindow().setHeight(600);
        gridmane.getScene().getWindow().setWidth(600);
        importGrid(gridmane, grid);


    }

    public void genLarge(ActionEvent actionEvent) throws IOException {

        Grid grid = new Grid(new Area(80, 80));
        grid.getPathfinder().shufflePartitions();
        grid.getPathfinder().fillPartitions();
        grid.getPathfinder().generateHallways();
        grid.getPathfinder().placeWalls();
        gridmane.getScene().getWindow().sizeToScene();
        gridmane.getScene().getWindow().setHeight(800);
        gridmane.getScene().getWindow().setWidth(800);
        importGrid(gridmane, grid);


    }

    private void importGrid(GridPane gridPane, Grid grid) {
        gridPane.getChildren().clear(); // remove old children

        for (int i = 0; i < grid.getSize().height; i++) {
            for (int j = 0; j < grid.getSize().width; j++) {
                if (grid.getContent()[j + (i * grid.getSize().width)] == TileSet.floorTile) {
                    changeSquare(gridPane, i, j, Color.WHITE, red);
                }
                else if (grid.getContent()[j + (i * grid.getSize().width)] == TileSet.wallTile) {

                    changeSquare(gridPane, i, j, Color.GRAY, black);

                }
                else {
                    changeSquare(gridPane, i, j, Color.BLACK, pink);
                }
            }
        }
    }

    private void changeSquare(GridPane gridPane, int xCoordinate, int yCoordinate, Color color, Image image) {
        Rectangle rect = new Rectangle();
        ImageView fimage = new ImageView(image);
        rect.setStroke(Color.BLACK);
        rect.setFill(color);
        rect.setWidth(10);
        rect.setHeight(10);
        gridPane.add(fimage, xCoordinate, yCoordinate);
    }




    public void clickGrid(javafx.scene.input.MouseEvent event) {
        Node source = (Node)event.getSource() ;
        Integer colIndex = gridmane.getColumnIndex(source);
        Integer rowIndex = gridmane.getRowIndex(source);
        System.out.println("Mouse clicked cell: " + colIndex + "And: " + rowIndex);


    }
}

主类

public class Main extends Application {

    Stage stage = new Stage();
    int val = 40;

    @Override
    public void start(Stage primaryStage) throws Exception {
        this.stage = primaryStage;
        setVal(val);

    }


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

    public void setVal(int i) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("/view.fxml"));
        stage.setTitle("Dungeon Generator");

        stage.setScene(new Scene(root, 450, 450));
        //primaryStage.setResizable(false);
        stage.sizeToScene();
        stage.show();
    }


}

FXML文件

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

<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>

<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="332.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
   <children>
      <MenuBar>
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
         <children>
            <Button alignment="CENTER" mnemonicParsing="false" onAction="#genSmall" prefHeight="27.0" prefWidth="64.0" text="Small" HBox.hgrow="ALWAYS">
               <HBox.margin>
                  <Insets left="20.0" />
               </HBox.margin>
            </Button>
            <Button alignment="CENTER" mnemonicParsing="false" onAction="#genMed" text="Medium" HBox.hgrow="ALWAYS">
               <HBox.margin>
                  <Insets left="20.0" />
               </HBox.margin>
            </Button>
            <Button alignment="CENTER" mnemonicParsing="false" onAction="#genLarge" prefHeight="27.0" prefWidth="66.0" text="Large" HBox.hgrow="ALWAYS">
               <HBox.margin>
                  <Insets left="20.0" />
               </HBox.margin>
            </Button>
         </children>
      </HBox>
      <StackPane>
         <children>
             <GridPane fx:id="gridmane" maxHeight="-Infinity" maxWidth="-Infinity" onMouseClicked="#clickGrid" VBox.vgrow="NEVER" />
         </children>
      </StackPane>
   </children>
</VBox>


推荐答案

因为您在<$ c注册了事件处理程序$ c> GridPane ,事件的来源是 GridPane 本身。您没有为 GridPane 设置行/列索引,并且它不包含任何有用的信息。

Since you register the event handler at the GridPane, the source of the event is the GridPane itself. You did not set the row/column index for the GridPane and it wouldn't contain any useful information.

在这种情况下,您需要从 MouseEvent 获取实际点击的节点:

In this case you need to get the node that was actually clicked from the MouseEvent:

public void clickGrid(javafx.scene.input.MouseEvent event) {
    Node clickedNode = event.getPickResult().getIntersectedNode();
    if (clickedNode != gridmane) {
        // click on descendant node
        Integer colIndex = GridPane.getColumnIndex(clickedNode);
        Integer rowIndex = GridPane.getRowIndex(clickedNode);
        System.out.println("Mouse clicked cell: " + colIndex + " And: " + rowIndex);
    }
}

在这种情况下,代码的工作方式与此类似您的 GridPane 中没有自己的子节点可能是相交的节点。

In this case the code works like this since the children of your GridPane don't have children of their own that could be the intersected node.

如果您想要添加可能拥有自己子项的子项,您需要通过节点层次结构,直到找到 GridPane的子项

If you want to add children that could have children of their own you need to go up through the node hierarchy until you find a child of the GridPane:

if (clickedNode != gridmane) {
    // click on descendant node
    Node parent = clickedNode.getParent();
    while (parent != gridmane) {
        clickedNode = parent;
        parent = clickedNode.getParent();
    }
    Integer colIndex = GridPane.getColumnIndex(clickedNode);
    Integer rowIndex = GridPane.getRowIndex(clickedNode);
    System.out.println("Mouse clicked cell: " + colIndex + " And: " + rowIndex);
}

这篇关于如何单击GridPane单元并让它执行操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆