Java事件绑定
我是使用java进行Windows应用程序开发的新手。 问题是这个“如何将事件绑定到自定义类方法?
我已经看到我可以注册监听器类来摆动组件来处理事件。 这没关系,但我必须实现一个实现例如ActionListener接口的类来处理事件然后实现actionPerformed方法。 这意味着我必须处理每个事件的一个类?
我不能让一个类“监听”来自所有组件的事件,并让这个类中的每个方法都进行事件处理吗?“
一个例子:
class MyEventListener { //pseudo code [no constructors, etc] public void handleSubmitFormBtn(Event e) { } //other methods go here handling events from other swing components }
注意:我不确定方法签名但我希望你明白这一点。
结论:一种方法来处理从摆动组件发出的事件……它可能吗? 是每个事件创建ONE类的唯一方法吗? 我不能将事件处理路由到单个类的特定方法吗?
你有几个选择,每个选择都有其特殊的好处/缺点。
匿名内部类
component.addActionListener( new ActionListener() { public void actionPerformed(final ActionEvent e) { outerClassesMethod(); } });
内心阶级
class Foo implements ActionListener { public void actionPerformed(final ActionEvent e) { outerClassMethod(); } }
外层阶级
public class Foo implements ActionListener { private final OuterClass target; public Foo(final OuterClass t) { target = t; } public void actionPerformed(final ActionEvent e) { target.targetClassMethod(); } }
class实现了listener
public class OuterClass implements ActionListener { public void actionPerformed(final ActionEvent e) { method(); } // somewhere else in the code { component.addActionListener(this); } }
每种方式都有好有坏。
匿名内部类不允许您执行您所要求的操作,它只能实现一个侦听器。
其他三个都将允许你做你想要的(只需添加,WindowListener到实现列表中为exaple)。 您可能希望实现侦听器方式的内部类或外部类能够执行您想要的操作。 我建议,因为侦听器可能非常高度耦合到您的程序,并且您将需要执行大量“if”语句来确定执行实际操作所执行的控件(使用evt.getSource()找出正在执行哪个控件,然后将其与实例变量共处以查看它是哪个。
但是,除非您使用内存受限设备(例如Android手机),否则您可能不应该为所有侦听器执行一种方法,因为它很容易导致非常糟糕的代码。 如果内存是一个问题,那就去吧,但如果不是,你最好做以下事情之一:
- 每个控件一个监听器类
- 所有控件的每种事件类型都有一个监听器类
- 每个事件类型每个控件一个监听器类
我更喜欢用以下方式编码,我发现它是最灵活的:
public class Outer extends JFrame { private final JButton buttonA; private final JButton buttonB; { buttonA = new JButton("A"); buttonB = new JButton("B"); } // do not put these in the constructor unless the Outer class is final public void init() { buttonA.addActionListener(new AListener()); buttonB.addActionListener(new BListener()); } private void aMethod() { } private void bMethod() { } public void AListener implements ActionListener { public void actionPerformed(final ActionEvent evt) { aMethod(); } } public void BListener implements ActionListener { public void actionPerformed(final ActionEvent evt) { bMethod(); } } }
我更喜欢这种方式,因为它强制将方法排除在侦听器之外,这意味着我只有一个地方可以查找代码(不会分散在整个内部类中)。 这也意味着aMethod()和bMethod()可以重用 – 如果代码在一个不实用的监听器中(这是可能的,但不值得付出努力)。
以上述方式做到这一点也是一致的,除非有充分的理由不这样做,否则我更喜欢与大多数事情保持一致。 例如在Android上我不这样做,因为类创建很昂贵(我仍然只有侦听器调用方法,但类本身实现了侦听器,我做了一个if语句)。
在摇摆中,你通常使用匿名类来处理你的事件,如下所示:
someControl.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // handle the event } });
虽然您基本上可以有一个类处理所有事件,并将其注册到所有处理程序,但如上所述,匿名类是处理事件的正确的循环习惯。
你可以找到更多信息@ http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html
您可以通过创建单个动作侦听器然后根据输入源进行切换来执行此操作,例如:
public void actionPerformed(ActionEvent e) { if (e.getSource() == buttonA) { doSomethingForButtonA(e); } else if (e.getSource() == buttonB) { doSomethingForButtonB(e); } }
但出于各种原因,这不是推荐的方法。 为什么在为每个要接收的事件创建侦听器时遇到问题? 它是用于处理UI事件的Java模型,如果其他人使用您的代码,或者您曾经使用其他代码,那么它将是预期的。
您可以拥有一个具有许多事件的侦听器方法的类:
class EventHandler implements ActionListener, ..., MouseListener { // implementation }
概念解决方案是实现OBSERVER PATTERN。
Melasse框架允许通过语法Binder.bind(/* source, target, options */)
将UI组件与创建类(甚至是匿名的)的模型粘合在一起。
例如,只有在文本字段中存在某些文本时才需要新类来启用操作/按钮: https : //github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided – 值 。 与显示/隐藏信息或错误标签相同。
支持大多数UI组件,所有Java Bean(具有属性更改支持)都是。