如何有效地添加多个事件处理程序

How to add multiple eventhandlers efficiently

我想要一个 18*18 的按钮网格,如果单击它们应该 return 它们在网格上的位置,以便检查所述方块的情况。 我尝试使用循环但

package application;

import code.Field;
import code.Square;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class ControllerClass {

    @FXML
    private VBox vbox;
    private HBox [] hbox;
    private Button [][] button;
    
    private Square selectedSquare;
    private Field field;
    @FXML
    public void initField() {
        
        hbox=new HBox[18];
        button=new Button[18][18];
        for(int i=0;i<18;i++) {
            hbox[i]=new HBox();
            hbox[i].setPrefHeight(60);
            vbox.getChildren().addAll(hbox[i]);
            for(int j=0;j<18;j++) {
                button[i][j]=new Button(i+";"+j);
                button[i][j].setPrefSize(60, 60);
                button[i][j].setOnAction(new EventHandler<ActionEvent>() {
                    @Override public void handle(ActionEvent e) {
                        selectedSquare=field.getSquare(i, j);
                    }
                });
                hbox[i].getChildren().add(button[i][j]);
            }
        }
    }
    
    
}

但是eventhandler显然不知道i和j的值。 那么我如何在不输入 324 事件处理程序的情况下执行此操作?

处理程序可以知道 ij 的值:您只需将它们复制到最终变量:

public void initField() {
    
    hbox=new HBox[18];
    button=new Button[18][18];
    for(int i=0;i<18;i++) {
        hbox[i]=new HBox();
        hbox[i].setPrefHeight(60);
        vbox.getChildren().addAll(hbox[i]);
        for(int j=0;j<18;j++) {
            button[i][j]=new Button(i+";"+j);
            button[i][j].setPrefSize(60, 60);
            final int row = i ;
            final int column = j ;
            button[i][j].setOnAction(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent e) {
                    selectedSquare=field.getSquare(row, column);
                }
            });
            hbox[i].getChildren().add(button[i][j]);
        }
    }
}

或者,定义一个创建和配置按钮的方法可能更优雅一些:

public void initField() {
    
    hbox=new HBox[18];
    button=new Button[18][18];
    for(int i=0;i<18;i++) {
        hbox[i]=new HBox();
        hbox[i].setPrefHeight(60);
        vbox.getChildren().addAll(hbox[i]);
        for(int j=0;j<18;j++) {
            button[i][j]=createButton(i, j);
            hbox[i].getChildren().add(button[i][j]);
        }
    }
}

private Button createButton(int i, int j) {
    Button button = new Button(i+";"+j);
    button.setPrefSize(60, 60);
    button.setOnAction(new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent e) {
            selectedSquare=field.getSquare(i, j);
        }
    });
    return button ;
}

(后一个版本可以工作是因为local变量ijcreateButton()方法中初始化后永远不会改变. 因此它们是“有效最终的”,因此可以被 lambda 表达式和匿名内部捕获 类.)

请注意,您很可能实际上不需要保留按钮数组:只需创建它们并设置它们的处理程序,然后将它们添加到场景图中:

public void initField() {
    
    hbox=new HBox[18];
    for(int i=0;i<18;i++) {
        hbox[i]=new HBox();
        hbox[i].setPrefHeight(60);
        vbox.getChildren().addAll(hbox[i]);
        for(int j=0;j<18;j++) {
            hbox[i].getChildren().add(createButton(i, j));
        }
    }
}