Reference clicked JButton inside ActionListener

17,546

Solution 1

Remember, ActionListener can be used on a number of different types of components, so the source reference is generalized. You need to cast to back to the expected value

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
        }
    }
});

While I know your ActionListener as it stands can pretty much guarantee that the source type of the Object will be a JButton, I never like blindly casting objects, but that's me

Solution 2

If you are receiving errors then you should post them but I am assuming it is because you aren't asserting that the source object is in fact a button. There are two straightforward solutions to what you are doing.

First is that since you are only adding one action listener to each button, you can assume that it is the object that the action event is referring to. Just note that the button either needs to be an instance variable or declared final:

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

Second, which would fix the cause of your error, is by asserting that the ActionEvent source object is in fact a button. This is done by checking that the source is an instance of JButton:

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

Solution 3

I went through and cleaned up your code a little bit. I'm not quite sure why your code had errors, but I didn't get any. I suggest, since you have common code, to reuse it like I did in an array. I also added a boolean to switch between players on each button click.

Lastly, I suggest setting up the JFrame in the constructor, or in a private method called by the constructor (more complex user interfaces might have a lot of code, and breaking it up is a good habit for maintainability of your code) like I showed below.

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();
    }
}
Share:
17,546
Amloelxer
Author by

Amloelxer

I code and eat tasty food around the world

Updated on June 04, 2022

Comments

  • Amloelxer
    Amloelxer almost 2 years

    I'm trying to write a Tic Tac Toe program using swing, but I seem to having some trouble. In my anonymous inner classes I attempt to set up the actionListener for each of my buttons, but I'm having trouble finding the type or the variable which will allow me to reference the buttons and set them to either X or Y. I tried e.getSource().setText() in my anonymous classes, but that came back with errors. Any thoughts? Thanks! 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();
    
    }
    
    
    }