如何添加监听多个按钮的动作事件?

29

我正在尝试弄清楚我的事件监听器(action listeners)哪里出错了。我按照多个教程操作,但是在使用事件监听器时,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,导致动作监听器从未被注册。 错误显示无法找到符号。


1
  1. 类名应该是每个单词的首字母大写。2) 除非添加功能,否则不要扩展框架。3) 如果扩展框架,则可能不需要在 main(String[]) 中实例化一个框架。4) 通常认为最好为每个需要的 GUI 元素添加一个动作监听器,而不是使用一个巨大的 if/else 级联的 actionPerformed(ActionEvent) 方法。5) 如果遵循第四条建议,问题基本上就消失了。
- Andrew Thompson
可以使用操作(Actions) - 对于许多执行相同操作的UI元素(例如工具栏和按钮),保持一致性是最佳选择。请参见http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html - tgkprog
11个回答

0

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

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

class MainWindow {
    Jbutton searchButton;
    Jbutton filterButton;
}

你可以使用我的“路由器”类将事件路由回你的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的初学者(不是编程),所以也许上面的代码有什么不妥之处,请在使用之前进行审核。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接