java - 为什么循环中添加到 JButton 的所有 ActionListener 都是相同的?

标签 java swing

好吧,我正在尝试制作一个 Swing 的国际象棋游戏。我有一个程序可以创建 JButton 的 8x8 二维数组。然后,我在循环中创建它们,执行诸如在白色/黑色之间来回切换并添加 Action 事件之类的操作。我遇到的问题是每个按钮都有相同的操作事件,并且它是最后创建的事件。第 8 行 H 列上的按钮是数组中所有按钮的操作监听器。这是我创建按钮并添加它们的代码片段。

我还有一个枚举列,例如从 int 到字符 1 到 H。 selectPosition 和 targetPosition 是具有两个成员列和行的对象。

public void initializeGui(boolean isWhite) {
    boolean shouldBeWhite = true;
    for(int i = 0; i< 8; i++){
        for(int j = 0; j < 8; j++){
            column = i+1;
            row = j+1;
            JButton square = new JButton();
            square.addActionListener(new ActionListener(){
                            @Override
                                public void actionPerformed(ActionEvent e) {
                                    final int thisRow = row;
                                    final int thisColumn = column;
                                    selectPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
                                    selectPosition.setRow(thisRow);
                                    if(isSelecting){
                                        System.out.print("Selecting square to move. Row: " + thisRow + " Column: " +  Columns.getColumnsFromInt(thisColumn));
                                        selectPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
                                        selectPosition.setRow(thisRow);
                                    } else{
                                        System.out.print("Targeting square to move to. Row: " + thisRow + " Column: " + Columns.getColumnsFromInt(thisColumn) + "\n");
                                        targetPosition.setColumn(Columns.getColumnsFromInt(thisColumn));
                                        targetPosition.setRow(thisRow);
                                    }
                                    System.out.println("");
                                isSelecting = !isSelecting;

                                }

            });
            if(shouldBeWhite){
                square.setBackground(Color.WHITE);
                shouldBeWhite = false;
            }else{
                square.setBackground(Color.BLACK);
                shouldBeWhite = true;
            }
            if (j == 7){
                shouldBeWhite = !shouldBeWhite;
            }
            chessBoardSquares[i][j] = square;
            gui.add(chessBoardSquares[i][j]);
        }
    }
    if(isWhite){
        setInitialPiecesWhiteStart();
    }else{
        setInitialPiecesBlackStart();
    }

}

作为此类的成员,进一步如下:

int column = 0, row = 0;

当我点击这些按钮中的任何一个时,我会看到打印内容

Selecting square to move. Row: 8 Column: H
Targeting square to move to. Row: 8 Column: H

Selecting square to move. Row: 8 Column: H
Targeting square to move to. Row: 8 Column: H

等等。我的问题是为什么这些按钮都被赋予相同的操作事件?我的逻辑演练类似于创建第一个按钮集 column = i+1 和 row = j+1,然后添加一个带有操作事件的操作监听器,该操作事件将当前行/列值设置为内部最终变量,然后打印出来与该操作事件关联的 thisRow 和 thisColumn。我是否覆盖了最后的值,或者范围是否错误?基本上我是如何错误地创建这些按钮操作监听器的?

最佳答案

你可以...

使用 actionCommand API 在按钮和 ActionListener 之间传递信息...

JButton btn = new JButton();
btn.setActionCommand(row + "x" + column);
btn.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();
        //...
    }
});

这里的问题是您依赖 String 解析来提取值,这很快就会变得困惑

你可以...

创建一个自定义的ActionListener,它接受您想要使用的值...

public class SquareActionListener implements ActionListener {
    private int column;
    private int row;

    public SquareActionListener(int row, int column) {
        this.row = row;
        this.column = column;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //...
    }
}

这将 ActionListener 与代码的其余部分分离,并为您提供所需的信息,尽管您可能还需要传递其他信息(例如模型)才能使其工作

你可以...

利用Action API,它旨在提供独立的工作单元,它通常是一个更可重用的解决方案,但可能有点超出您现在的需要

public class SquareAction extends AbstractAction {
    private int column;
    private int row;

    public SquareAction(int row, int column) {
        this.row = row;
        this.column = column;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //...
    }
}

这看起来很像最后一个建议,但您实际上不是将其添加为按钮的 ActionListener,而是直接将其应用到按钮...

JButton btn = new JButton(new SquareAction(row, column));

然后该按钮使用其他属性(我尚未设置)来设置自身

关于java - 为什么循环中添加到 JButton 的所有 ActionListener 都是相同的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42568798/

相关文章:

java - 将 csv 导入到 JTable

java - 将神经网络应用于学生考勤系统

java - 将 JPA 实体一分为二?

java - 老虎机随机化

java - Swing 窗口被卡住,不显示内容

Java 图形用户界面 : How to Set Focus on JButton in JPanel on JFrame?

java - 在 Java 中的 JPanel 上绘制随机不重叠的矩形

java - 基于条件和测试类注释禁用 TestNG 测试

Java 日历 : Why are UTC offsets being reversed?

java - 如何在按下按钮时循环播放声音并在释放时停止播放?