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

时间:2011-05-09 11:31:33

标签: java swing jbutton actionlistener

我想弄清楚我对动作听众做错了什么。我正在学习多个教程,但是当我尝试使用动作监听器时,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,错误说无法找到符号。

11 个答案:

答案 0 :(得分:35)

静态方法中没有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)
    }  

}

答案 1 :(得分:20)

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

  • 您有多个需要执行相同操作的事件源(例如,如果您希望使用能够按文本字段上的回车键作为单击旁边按钮的替代方法)
  • 您没有对生成事件的组件的引用

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

答案 2 :(得分:9)

以下是基于我的评论的源的修改形式。注意,应该构建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);
    }
}

答案 3 :(得分:3)

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

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

  • 不要扩展您不需要的类。 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

答案 4 :(得分:2)

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

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

或者您将button1设为全局变量。

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

首先,使用super()和构造函数正确扩展JFrame 然后向框架添加动作侦听器并添加按钮。

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

答案 8 :(得分:0)

我使用“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
    }
}

我希望其他答案也很有用。

答案 9 :(得分:0)

这里有很好的答案,但让我来谈谈添加可监听多个按钮的动作监听器的更全局的点。

有两种流行的方法。

使用通用操作侦听器

您可以在actionPerformed(ActionEvent e)实现中获取操作的来源:

JButton button1, button2; //your button

@Override
public void actionPerformed(ActionEvent e) {

    JButton actionSource = (JButton) e.getSource();

    if(actionSource.equals(button1)){
        // YOU BUTTON 1 CODE HERE
    } else if (actionSource.equals(button2)) {
        // YOU BUTTON 2 CODE HERE
    }
}

使用ActionCommand

使用这种方法,您可以设置按钮的actionCommand字段,稍后将允许您使用switch

button1.setActionCommand("actionName1");
button2.setActionCommand("actionName2");

后来:

@Override
public void actionPerformed(ActionEvent e) {
    String actionCommand = ((JButton) e.getSource()).getActionCommand();

    switch (actionCommand) {
        case "actionName1": 
            // YOU BUTTON 1 CODE HERE
        break;
        case "actionName2": 
            // YOU BUTTON 2 CODE HERE
        break;
    }
}

退回到learn more about JFrame Buttons, Listeners and Fields

答案 10 :(得分:0)

这是一个很老的问题。我想没人再在乎了。但是我想发表我的方法,以防对某人有所帮助。

使用我的方法,您可以以“经典方式”编写按钮单击事件处理程序,就像在VB或MFC中一样;)

假设我们有一个包含2个按钮的框架窗口类:

class MainWindow {
    Jbutton searchButton;
    Jbutton filterButton;
}

您可以使用我的“ router”类将事件路由回您的MainWindow类:

class MainWindow {
    JButton searchButton;
    Jbutton filterButton;
    ButtonClickRouter buttonRouter = new ButtonClickRouter(this);

    void initWindowContent() {
        // create your components here...

        // setup button listeners
        searchButton.addActionListener(buttonRouter);
        filterButton.addActionListener(buttonRouter);
    }

    void on_searchButton() {
        // TODO your handler goes here...
    }

    void on_filterButton() {
        // TODO your handler goes here...
    }
}

你喜欢吗? :)

如果您喜欢这种方式并且讨厌Java的匿名子类方式,那么您和我一样大。 “ addActionListener(new ActionListener {...})”的问题在于,它将所有按钮处理程序压缩到一个外部方法中,该外部方法使程序看起来更有线。 (以防您在一个窗口中有许多按钮)

最后,路由器类别在下面。您可以将其复制到程序中,而无需进行任何更新。

仅需提一下:此路由器类必须可以访问按钮字段和事件处理程序方法!简而言之,如果将此路由器类复制到程序的同一程序包中,则按钮字段和方法必须是程序包可访问的。否则,它们必须是公开的。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ButtonClickRouter implements ActionListener {
    private Object target;

    ButtonClickRouter(Object target) {
        this.target = target;
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        // get source button
        Object sourceButton = actionEvent.getSource();

        // find the corresponding field of the button in the host class
        Field fieldOfSourceButton = null;
        for (Field field : target.getClass().getDeclaredFields()) {
            try {
                if (field.get(target).equals(sourceButton)) {
                    fieldOfSourceButton = field;
                    break;
                }
            } catch (IllegalAccessException e) {
            }
        }

        if (fieldOfSourceButton == null)
            return;

        // make the expected method name for the source button
        // rule: suppose the button field is 'searchButton', then the method
        // is expected to be 'void on_searchButton()'
        String methodName = "on_" + fieldOfSourceButton.getName();

        // find such a method
        Method expectedHanderMethod = null;
        for (Method method : target.getClass().getDeclaredMethods()) {
            if (method.getName().equals(methodName)) {
                expectedHanderMethod = method;
                break;
            }
        }

        if (expectedHanderMethod == null)
            return;

        // fire
        try {
            expectedHanderMethod.invoke(target);
        } catch (IllegalAccessException | InvocationTargetException e) { }
    }
}

我是Java(不是编程)的初学者,所以上面的代码中可能有什么不合适的内容。请在使用前对其进行检查。