簡體   English   中英

為什么將我所有的ActionListener循環添加到JButton中都相同?

[英]Why are all my ActionListener's added to JButtons in a loop identical?

好吧,所以我試圖做一個象棋游戲。 我有一個程序可以創建JButton的8x8二維數組。 然后,我將它們全部循環創建,以完成諸如在白色/黑色之間來回移動並添加一個動作事件之類的工作。 我遇到的問題是每個按鈕都具有相同的動作事件,並且是在行8列H上的最后一個IE按鈕創建的事件是數組中所有按鈕的動作偵聽器。 這是我創建按鈕並添加按鈕的代碼段。

我也有一個枚舉列,例如從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));

然后,該按鈕使用其他屬性(我尚未設置)自行設置

制作井字游戲時,我遇到了同樣的問題。 我使用每個按鈕的哈希碼來追溯實際按下了哪個按鈕。 這是我的按鈕設置:

hashcodes= new ArrayList<Integer>();

    for (int i=1;i<=9;i++) {
        JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setHash(button.hashCode());
                testWinner();
                testDraw();
            }
        });
        hashcodes.add(button.hashCode());
        panel.add(button);
    }
}

    private void setHash(int hashcode) {
            for (int h:hashcodes) {
                if (h==hashcode) {
                    //do stuff
                }
            }
        }

這是我的Test課程,並且效果很好。

public class Test extends javax.swing.JFrame {

    private javax.swing.JButton[][] buttons;

    private final int ROW = 8;
    private final int COLUMN = 8;

    public Test() {
        initComponents();
    }

    private void initComponents() {
        this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        this.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);
        this.buttons = new javax.swing.JButton[ROW][COLUMN];
        this.setLayout(new java.awt.GridLayout(ROW, COLUMN));
        for (int i = 0; i < ROW; i++) {
            for (int j = 0; j < COLUMN; j++) {
                final int row = i;
                final int column = j;
                buttons[i][j] = new javax.swing.JButton(
                        String.format("Button %d-%d", i, j));
                buttons[i][j].addActionListener(new java.awt.event.ActionListener() {
                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent e) {
                    //    System.out.println(
                    //            String.format("You have just pressed the button at row %d and column %d", row, column));
                        javax.swing.JOptionPane.showMessageDialog(
                                Test.this, String.format("You have just pressed the button at row %d and column %d", row, column));
                    }
                });
                this.add(buttons[i][j]);
            }
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Test().setVisible(true);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM