How to add action listener that listens to multiple buttons
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
.
user519670
Updated on December 04, 2020Comments
-
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 seebutton1
, errors saying cannot find symbol.