如何添加侦听多个按钮的动作侦听器

我试图弄清楚我对动作听众做错了什么。 我正在关注多个教程,但是当我尝试使用动作监听器时,netbeans和eclipse会给我错误。

下面是一个简单的程序,我试图让一个按钮工作。

我究竟做错了什么?

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

动作监听器永远不会注册,因为if(e.getSource() == button1)它看不到button1 ,错误说无法找到符号。

静态方法中没有this指针。 (我不相信这段代码甚至会编译。)

你不应该在像main()这样的静态方法中做这些事情; 在构造函数中设置。 我没有编译或运行它来查看它是否真的有效,但试一试。

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

我很惊讶没有人提到使用动作命令。 这是关联源和侦听器的非常标准的方式。 它非常有用;

  • 你有多个事件源需要做同样的事情(例如,如果你想使用能够按文本字段上的回车键作为单击旁边的按钮的替代方案)
  • 您没有对生成事件的组件的引用

看到;

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

这是基于我的评论的源的修改forms。 请注意,应该在EDT上构建和更新GUI,尽管我没有那么做。

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

问题是button1是一个局部变量。 您可以通过更改添加actionListener的方式来实现。

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

或者让button1成为全局变量。

你已经被告知如何对你眼前的问题进行排序,但我认为这里有更重要的问题。

  • 坚持惯例。 即使是丢弃代码。 这意味着类名的初始案例。

  • 不要扩展您不需要的类。 JFrame应该很少扩展。 实际上,您不会创建派生类的实例!

  • 不要将一堆东西捆绑到一个类中。 特别是,您通常一次只能对一个主类或接口进行子类型化(不包括Comparable )。

  • 始终在AWT事件调度线程(EDT)上进行交互,包括构造,Swing / AWT GUI。 这是丑陋和冗长的,但那是你的Java。

  • 检查事件的来源是一个黑客攻击。 听众很小,所以你甚至不能说出蹩脚的表演借口。

所以:

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

如果需要从侦听器中的封闭方法访问任何变量,请将它们设为final

第一个问题是button1main方法的局部变量,因此actionPerformed方法无法访问它。

第二个问题是ActionListener接口是由类calc实现的,但是在main方法中没有创建此类的实例。

执行所需操作的常用方法是创建calc实例并使button1成为calc类的字段。

您在main方法中声明button1,因此您无法在actionPerform中访问它。 你应该在课堂上把它变成全球性的。

  JButton button1; public static void main(String[] args) { JFrame calcFrame = new JFrame(); calcFrame.setSize(100, 100); calcFrame.setVisible(true); button1 = new JButton("1"); button1.addActionListener(this); calcFrame.add(button1); } public void actionPerformed(ActionEvent e) { if(e.getSource() == button1) } 

首先,使用super()和构造函数正确执行JFrame,然后将actionlisteners添加到框架并添加按钮。

 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 { JButton button1 = new JButton("1"); JButton button2 = new JButton("2"); public Calc() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(100, 100); button1.addActionListener(this); button2.addActionListener(this); calcFrame.add(button1); calcFrame.add(button2); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if(source == button1) { \\button1 code here } else if(source == button2) { \\button2 code here } } public static void main(String[] args) { JFrame calcFrame = new JFrame(); calcFrame.setVisible(true); } } 

我使用“e.getActionCommand()。contains(CharSecuence s)”,因为我来自MVC上下文,而Button在View类中声明,但actionPerformed调用发生在控制器中。

 public View() { .... buttonPlus = new Button("+"); buttonMinus = new Button("-"); .... } public void addController(ActionListener controller) { buttonPlus.addActionListener(controller); buttonMinus.addActionListener(controller); } 

我的控制器类实现ActionListener,因此,当覆盖actionPerformed时:

 public void actionPerformed(ActionEvent e) { if(e.getActionCommand().contains("+")) { //do some action on the model } else if (e.getActionCommand().contains("-")) { //do some other action on the model } } 

我希望其他答案也有用。