在ActionListener中引用点击的JButton

4

我正在尝试使用swing编写一个井字棋程序,但似乎遇到了一些问题。在我的匿名内部类中,我尝试为每个按钮设置actionListener,但是我找不到类型或变量,以便我可以引用这些按钮并将它们设置为X或Y。我尝试在我的匿名类中使用e.getSource().setText(),但出现了错误。有什么想法吗? 谢谢! Alex

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TicTacToe  {

public JFrame frame;
public JLabel label;
public JPanel panel;

public static int counter;



public void go()
{ 
    frame = new JFrame("TicTacToe");
    frame.setSize(500, 500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel = new JPanel();
    panel.setLayout(new GridLayout(3,3,10,10));
    frame.add(BorderLayout.CENTER, panel);
    label= new JLabel("TIC TAC TOE");
    frame.add(BorderLayout.NORTH, label);

    ; 


    JButton button1 = new JButton("Button 1");
    JButton button2 = new JButton("Button 1");
    JButton button3 = new JButton("Button 1");
    JButton button4 = new JButton("Button 1");
    JButton button5 = new JButton("Button 1");
    JButton button6 = new JButton("Button 1");
    JButton button7 = new JButton("Button 1");
    JButton button8 = new JButton("Button 1");
    JButton button9 = new JButton("Button 1");





    button1.addActionListener(new ActionListener(){ 
        public void actionPerformed(ActionEvent e)
        {


        }
    });

    button2.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button3.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button4.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button5.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button6.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button7.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button8.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    button9.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e)
        {

        }
    });

    panel.add(button1);
    panel.add(button2);
    panel.add(button3);
    panel.add(button4);
    panel.add(button5);
    panel.add(button6);
    panel.add(button7);
    panel.add(button8);
    panel.add(button9);
    frame.setVisible(true);
    panel.setVisible(true);

}


public static void main(String[] args)
{
    TicTacToe gui = new TicTacToe();
    gui.go();

}


}
3个回答

12

请记住,ActionListener可以用于多种不同类型的组件,因此源引用是泛化的。您需要将其转换回预期值

button9.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
        Object source = e.getSource();
        if (source instanceof JButton) {
            JButton btn = (JButton)source;
            // Go ahead and do what you like
        }
    }
});

虽然我知道你的ActionListener目前几乎可以保证Object的源类型将是一个JButton,但我从不喜欢盲目地转换对象,不过这只是我的个人见解。


另一个问题。这种情况下确定胜者的最佳方法是什么?比如我可以制作一个计数器,然后使用 ((JButton) source).setText("O"); 或者 ((JButton) source).setText("X"); - Amloelxer
实际上,最好的方法是建立某种模型。这将允许您检查游戏状态并确定哪些单元格被选中以及由谁选择。每当玩家选择一个按钮时,我会更新模型。这个过程的一部分是让模型检查是否有赢家,并触发适当的事件。 - MadProgrammer

2
如果你收到了错误信息,那么你应该发布它们,但我假设这是因为你没有断言源对象实际上是一个按钮。你所做的事情有两个简单的解决方案。 首先,由于你只向每个按钮添加了一个动作监听器,因此可以假定它是动作事件所引用的对象。只需注意,该按钮必须是实例变量或声明为final:
    button1.addActionListener(new ActionListener(){ 
        @Override
        public void actionPerformed(ActionEvent e)
        {
            button1.setText("X/Y");
        }
    });

其次,解决您的错误的方法是通过断言ActionEvent源对象实际上是一个按钮来修复。这可以通过检查源是否是JButton的实例来完成:

    button1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() instanceof JButton) {
                ((JButton) e.getSource()).setText("X/Y");
            }
        }
    });

1
我唯一的评论是,请确保强调在您的第一个示例中,JButton 将需要成为实例变量或 final ;) - MadProgrammer

1
我稍微整理了你的代码。我不太确定为什么你的代码会出错,但我没有遇到过任何问题。我建议你像我一样在数组中重用公共代码。我还添加了一个布尔值,在每次按钮点击时切换玩家。
最后,我建议在构造函数中设置JFrame,或者在构造函数调用的私有方法中设置(更复杂的用户界面可能会有很多代码,将其分解是保持代码可维护性的好习惯),就像我下面展示的那样。
import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TicTacToe {
    public static final boolean PLAYER_X = false;
    public static final boolean PLAYER_O = true;

    public static int counter;

    private JFrame frame;
    private JLabel label;
    private JPanel panel;
    private JButton[] buttons;
    private boolean player;

    public TicTacToe() {
        frame = new JFrame("TicTacToe");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel = new JPanel();
        panel.setPreferredSize(new Dimension(500, 500));
        panel.setLayout(new GridLayout(3, 3, 10, 10));
        frame.add(BorderLayout.CENTER, panel);

        label = new JLabel("TIC TAC TOE");
        frame.add(BorderLayout.NORTH, label);

        /* Set the initial player turn to player X */
        player = PLAYER_X;

        /* Create the JButtons  */
        buttons = new JButton[9];

        /* Loop through and set all of them up */
        for (int i = 0; i < buttons.length; i++) {
            buttons[i] = new JButton();
            buttons[i].addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (e.getSource() instanceof JButton) {
                        ((JButton)e.getSource()).setText(player ? "O" : "X"); /* Set button text */
                        player = !player; /* Switch turns */
                    }
                }
            });

            /* Add all of the buttons to the panel. */
            panel.add(buttons[i]);
        }

        /* Pack the frame to the contents. Basically a "fit to contents". */
        frame.pack();
    }

    public void go() {
        frame.setVisible(true);
        panel.setVisible(true);
    }

    public static void main(String[] args) {
        TicTacToe gui = new TicTacToe();
        gui.go();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接