Java事件绑定

时间:2009-03-21 10:38:27

标签: java swing event-handling

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

注意:我不确定方法签名,但我希望你明白这一点。

结论:处理从swing组件触发的事件的一种方法......有可能吗?是每个事件创建ONE类的唯一方法吗?我不能将事件处理路由到单个类的特定方法吗?

6 个答案:

答案 0 :(得分:4)

在摇摆中,您通常使用匿名类来处理您的事件,如下所示:

  someControl.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
          // handle the event
      }
  });

虽然你基本上可以有一个类来处理所有事件,并将它注册到所有处理程序,但如上所述,匿名类是处理事件的正确循环习惯。

您可以找到更多信息@ http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html

答案 1 :(得分:2)

您有几个选择,每个选择都有其特殊的好处/缺点。

匿名内部课程

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

类实现侦听器

public class OuterClass
    implements ActionListener
{
    public void actionPerformed(final ActionEvent e)
    {
        method();
    }

    // somewhere else in the code
    {
         component.addActionListener(this);
    }
}

每种方式都有好有坏。

匿名内部类不允许你做你想要的,它只能实现一个监听器。

其他三个都允许你做你想做的事情(只需将WindowListener添加到实现列表中即可)。您可能希望实现侦听器方式的内部类或外部类能够执行您想要的操作。我建议,因为监听器很可能与您的程序高度耦合,并且您需要执行一大组“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语句)。

答案 2 :(得分:1)

您可以通过创建单个动作侦听器来执行此操作,然后根据输入源进行切换,如下所示:

public void actionPerformed(ActionEvent e) {
   if (e.getSource() == buttonA) {
       doSomethingForButtonA(e);
   } else if (e.getSource() == buttonB) {
       doSomethingForButtonB(e);
   }
}

但出于各种原因,这不是推荐的方法。为什么在为每个要接收的事件创建侦听器时遇到问题?它是用于处理UI事件的Java模型,如果其他人使用您的代码,或者您曾经使用其他代码,那么它将是您所期望的。

答案 3 :(得分:0)

您可以拥有一个具有多个事件的侦听方法的类:

class EventHandler implements ActionListener, ..., MouseListener {
   // implementation
}

答案 4 :(得分:0)

概念解决方案是实现OBSERVER PATTERN。

答案 5 :(得分:0)

Melasse框架允许将UI组件与模型粘合,而不创建类(甚至是匿名的),语法为Binder.bind(/* source, target, options */)

例如,仅当文本字段中存在某些文本时才需要新类来启用操作/按钮:https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value。与显示/隐藏信息或错误标签相同。

支持大多数UI组件,所有Java Bean(具有属性更改支持)都是。