How to add action listener that listens to multiple buttons

226,250

Solution 1

There is no this pointer in a static method. (I don't believe this code will even compile.)

You shouldn't be doing these things in a static method like main(); set things up in a constructor. I didn't compile or run this to see if it actually works, but give it a try.

public class Calc extends JFrame implements ActionListener {

    private Button button1;

    public Calc()
    {
        super();
        this.setSize(100, 100);
        this.setVisible(true);

        this.button1 = new JButton("1");
        this.button1.addActionListener(this);
        this.add(button1);
    }


    public static void main(String[] args) {

        Calc calc = new Calc();
        calc.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button1)
    }  

}

Solution 2

I'm amazed that nobody has mentioned using an action command. This is a pretty standard way of associating sources and listeners. Its really useful if;

  • you have multiple event sources that need to do the same thing (eg if you want the use to be able to press the enter key on a text field as an alternative to clicking a button next to it)
  • you don't have a ref to the component generating the event

see;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;    
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class DontExtendJFrame implements ActionListener {

  private enum Actions {
    HELLO,
    GOODBYE
  }

  public static void main(String[] args) {

    DontExtendJFrame instance = new DontExtendJFrame();

    JFrame frame = new JFrame("Test");
    frame.setLayout(new FlowLayout());
    frame.setSize(200, 100);

    JButton hello = new JButton("Hello");
    hello.setActionCommand(Actions.HELLO.name());
    hello.addActionListener(instance);
    frame.add(hello);

    JButton goodbye = new JButton("Goodbye");
    goodbye.setActionCommand(Actions.GOODBYE.name());
    goodbye.addActionListener(instance);
    frame.add(goodbye);

    frame.setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    if (evt.getActionCommand() == Actions.HELLO.name()) {
      JOptionPane.showMessageDialog(null, "Hello");
    } else if (evt.getActionCommand() == Actions.GOODBYE.name()) {
      JOptionPane.showMessageDialog(null, "Goodbye");
    }
  }
}

Solution 3

Here is a modified form of the source based on my comment. Note that GUIs should be constructed & updated on the EDT, though I did not go that far.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JFrame;

public class Calc {

    public static void main(String[] args) {

        JFrame calcFrame = new JFrame();

        // usually a good idea.
        calcFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JButton button1 = new JButton("1");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                JOptionPane.showMessageDialog(
                    button1, "..is the loneliest number");
            }
        });

        calcFrame.add(button1);

        // don't do this..
        // calcFrame.setSize(100, 100);

        // important!
        calcFrame.pack();

        calcFrame.setVisible(true);
    }
}

Solution 4

The problem is that button1 is a local variable. You could do it by just change the way you add the actionListener.

button.addActionListener(new ActionListener() {  
            public void actionPerformed(ActionEvent e)
            {
                //button is pressed
                System.out.println("You clicked the button");
            }});

Or you make button1 a global variable.

Solution 5

You've been told how to sort your immediate problem, but I think there are more important problems here.

  • stick with conventions. Even for throw-away code. That means initial cases for class names.

  • Don't extend classes you don't need to. JFrame should rarely be extended. In fact, you don't create an instance of your derived class!!!

  • Don't bundle a bunch of things into one class. In particular, you should generally only subtype at most one main class or interface at a time (things like Comparable not included).

  • Always interact, including construct, Swing/AWT GUIs on the AWT Event Dispatch Thread (EDT). It's ugly and verbose, but that's Java for you.

  • Checking a source of an event is a bit of hack. Listeners are small, so you can't even claim the lame performance excuse.

So:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;


public class Calc {
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
            runEDT();
        }});
    }
    private static void runEDT() {
        assert java.awt.EventQueue.isDispatchThread();

        JFrame frame = new JFrame();

        frame.setSize(100, 100);

        JButton button1 = new JButton("1");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                ...
            }
        });

        frame.add(button1);

        frame.setVisible(true);
    }
}

If you need to access any of the variables from the enclosing method within the listener, make them final.

Share:
226,250
user519670
Author by

user519670

Updated on December 04, 2020

Comments

  • user519670
    user519670 over 3 years

    I'm trying to figure out what i am doing wrong with action listeners. I'm following multiple tutorials and yet netbeans and eclipse are giving me errors when im trying to use an action listener.

    Below is a simple program that im trying to get a button working in.

    What am i doing wrong?

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    
    
    public class calc extends JFrame implements ActionListener {
    
    
    
        public static void main(String[] args) {
    
            JFrame calcFrame = new JFrame();
    
            calcFrame.setSize(100, 100);
            calcFrame.setVisible(true);
    
            JButton button1 = new JButton("1");
            button1.addActionListener(this);
    
            calcFrame.add(button1);
        }
    
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == button1)
        }  
    
    }
    

    the action listener is never registered because with the if(e.getSource() == button1) it cant see button1, errors saying cannot find symbol.