【问题标题】:Record the last JButton pressed in a grid of JButtons记录在 JButton 网格中按下的最后一个 JButton
【发布时间】:2017-03-03 23:03:44
【问题描述】:

大家好,我正在尝试使用 java 创建一个简单的国际象棋游戏。我有一个 [8][8] JButtons 数组的板。我为每个人分配了一个新的 SquareListener,它是一个扩展 BoardListner 的类,它是一个实现 Action Listener 的超类。我想记录当前按下的按钮是否等于最后按下的按钮。我正在存储在超类中按下的 JButton 实例,并在 SqaureListener actionPerformed 方法中引用该实例。这是我为按钮创建的类的示例。

public class SquareListener extends BoardListener {
private int row;
private int column;


public SquareListener(int row, int column){
    this.setRow(row);
    this.setColumn(column);
}

@Override
public void actionPerformed(ActionEvent ae){
    JButton buttonPressed = (JButton) ae.getSource();
    if(buttonPressed == super.lastButtonPressed){
        System.out.println("This is the button you last pressed");
    }else{
        System.out.println("This is a new button");
    }
    super.lastButtonPressed = buttonPressed;
}

这是我存储 isSelecting 数据的超类

public class BoardListener implements ActionListener {

    private boolean isSelectingInsteadOfTargeting = true;
    JButton lastButtonPressed = new JButton();

    @Override
     public void actionPerformed(ActionEvent arg0) {
    // TODO Auto-generated method stub
    }

    public boolean isSelectingInsteadOfTargeting() {
        return isSelectingInsteadOfTargeting;
    }

    public void setSelectingInsteadOfTargeting(boolean isSelectingInsteadOfTargeting) {
    this.isSelectingInsteadOfTargeting = isSelectingInsteadOfTargeting;
    }

}

我希望每次按下按钮时都会将该按钮的实例传递给 buttonPressed 并与 BoardListener 中存储的内容进行比较,然后将其打印出来,然后将 buttonPressed 分配给超级成员。相反,我得到的行为是,如果我按下一个按钮,它总是会返回“这是你最后按下的按钮”,即使我在两者之间按下了一个新按钮。我这样做的方式有问题吗?有没有更简单的方法?

这是我存储按钮并将其分配给动作侦听器的附加代码

public Board(boolean _isWhite){
    gui = new JPanel(new GridLayout(8,8));
    chessBoardSquares = new Square[8][8];
    boolean shouldBeWhite = true;
    for(int i = 0; i < 8; i++){
        for(int j= 0; j < 8; j++){
            Square square = new Square(i,j);
            square.getButton().addActionListener(new SquareListener(i,j));
            if(shouldBeWhite){
                square.getButton().setBackground(Color.WHITE);
                shouldBeWhite = false;
            }else{
                square.getButton().setBackground(Color.BLACK);
                shouldBeWhite = true;
            }
            if (j == 7){
                shouldBeWhite = !shouldBeWhite;
            }
            chessBoardSquares[i][j] = square;
            gui.add(chessBoardSquares[i][j].getButton());
        }
    }
    BoardFactory boardFactory = new BoardFactory();
    if(_isWhite){
        updateBoardIconsBasedOnCurrentBoardArray(boardFactory.getBlackStartArray());
    }else{
        //getblack start array and invoke method to change button icons based on array
    }
}

【问题讨论】:

  • 您能否将注册侦听器的代码添加到您的按钮。我怀疑每个按钮都有 64 个不同的侦听器。在这种情况下,我认为应该有一个 Board 类,它可以作为静态变量跟踪最近和上一次的按钮点击。
  • 刚刚添加了它,让我知道你的想法我显然还有其他一些补充课程,但你可能可以从中得到要点

标签: java swing


【解决方案1】:

我们不需要一个 8 x 8 的整个网格,但可能需要一个 2 x 2 可以由您缩放到 8 x 8 的网格。

此代码比较最后点击按钮的坐标。

您可以为所有按钮使用一个 ActionListener...

例如:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TwiceButtonPressed {

    private JFrame frame;

    private JButton[][] buttons;

    private JLabel label;
    private JLabel sameButtonLabel;

    private JPanel pane;

    private boolean sameButtonPressed;

    private static final int rows = 2;
    private static final int cols = 2;

    private int buttonRow = -1;
    private int buttonCol = -1;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TwiceButtonPressed().createAndShowGui()); 
    }

    public void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());

        sameButtonPressed = false;

        label = new JLabel("Button pressed: NONE");
        sameButtonLabel = new JLabel("Same button pressed: " + sameButtonPressed);

        pane = new JPanel();
        pane.setLayout(new GridLayout(rows, cols));

        buttons = new JButton[rows][cols];

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                buttons[i][j] = new JButton(i + "" + j);
                buttons[i][j].addActionListener(listener);
                pane.add(buttons[i][j]);
            }
        }

        frame.add(sameButtonLabel, BorderLayout.NORTH);
        frame.add(pane, BorderLayout.CENTER);
        frame.add(label, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    if (e.getSource().equals(buttons[i][j])) {
                        label.setText("Button pressed: " + buttons[i][j].getText());
                        System.out.println(buttonRow + "==" + i + "***" + buttonCol + "==" + j);
                        if (buttonRow == i && buttonCol == j) {
                            sameButtonPressed = true;
                        } else {
                            sameButtonPressed = false;
                        }
                        sameButtonLabel.setText("Same button pressed: " + sameButtonPressed);
                        buttonRow = i;
                        buttonCol = j;
                    }
                }
            }
        }
    };
}

另外,您可以将白/黑算法更改为以下内容:

for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        buttons[i][j] = new JButton() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(50, 50);
            }
        };
        buttons[i][j].addActionListener(listener);
        if (i % 2 == 0) {
            if (j % 2 == 0) {
                buttons[i][j].setBackground(Color.BLACK);
            } else {
                buttons[i][j].setBackground(Color.WHITE);
            }
        } else {
            if (j % 2 != 0) {
                buttons[i][j].setBackground(Color.BLACK);
            } else {
                buttons[i][j].setBackground(Color.WHITE);
            }
        }
        pane.add(buttons[i][j]);
    }
}

【讨论】:

  • 感谢您的回答,这真的很有帮助,您是否认为我的白/黑算法效率低下/错误?我想,因为它工作得很好。这种心态对我将来可能编写的更难的算法有害吗?
  • @BrendanRobert 并不是说​​它没有效率,而是更难理解/阅读。它和我的一样,我只是向你展示了另一种方法。希望对你有帮助:)
【解决方案2】:

每个按钮都有自己的监听器,每个监听器都有自己的 lsstButonPressed 字段,这样就不行了。

对所有按钮使用相同的侦听器instance,或将最后按下的按钮存储在板上(或所有侦听器共享的另一个对象中)。

另外,您不需要super 来访问lastButtonPressed。

还有这个

JButton lastButtonPressed = new JButton();

创建一个新的 JButton 是徒劳的。只需将该字段留空即可。

【讨论】:

  • 我应该在board类中使用静态字段来存储全局点击数据吗?
  • 没有。一个非静态的实例字段会更好。
  • 好的,但我遇到的问题是如何为每个按钮设置一个单独的动作监听器,但让它们实际更改我在 main 中实例化的 Board 对象。如果它是一个非静态实例字段,那么动作侦听器如何在主方法之外操作这些字段?
  • 将板子(或包含板子最后按下的按钮的对象)传递给侦听器的构造函数。
  • 这样的东西看起来怎么样?如果我正在构建 64 个动作侦听器并将板对象传递给每个侦听器,我不会在每个侦听器中都有一个单独的板实例吗?另外,我将如何操纵董事会的非静态成员?例如,如果我移动一个棋子,我如何更改目标方块图标以随着移动而更新?我对 OOP 比较陌生,而且对摇摆也很陌生,所以如果这些都是琐碎的问题,我还没有掌握所有内容,请原谅我
猜你喜欢
  • 1970-01-01
  • 2017-07-18
  • 2014-01-12
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2013-08-02
  • 2020-08-24
相关资源
最近更新 更多