好的,所以我想尝试下棋。我有一个程序,可以创建一个JButton 8x8的二维数组。然后我在一个循环中创建它们,像在白色/黑色之间来回移动并添加动作事件。我遇到的问题是每个按钮都有相同的动作事件,它是最后创建的事件。第8行H列上的按钮是数组中所有按钮的动作侦听器。这是一段代码,我正在创建按钮并添加它们。
我还有一个Enum Columns,例如从int到character 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与该动作事件相关联。我是否在最后覆盖了这些值,还是我的范围错了?基本上我是如何错误地创建这些按钮动作侦听器的?
答案 0 :(得分:1)
使用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));
然后该按钮使用其他属性(我没有设置)来设置自己
答案 1 :(得分:0)
在制作一个井字游戏时我遇到了同样的问题。我使用每个按钮的哈希码来追溯实际推送的按钮。这就是我的按钮设置:
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
}
}
}
答案 2 :(得分:0)
这是我的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);
}
}