Привязка событий Java - PullRequest
       35

Привязка событий Java

1 голос
/ 21 марта 2009

Я новичок в разработке приложений для Windows с использованием Java. Вопрос такой: «Как связать события с пользовательскими методами класса?

Как я уже видел, я могу зарегистрировать классы слушателей, чтобы качать компоненты для обработки событий. Это нормально, но я должен реализовать класс, который реализует, например, интерфейс ActionListener для обработки события и реализации метода actionPerformed. Что означает ОДИН класс для каждого события, которое я должен обработать?

Разве я не могу иметь ОДИН класс, "слушающий" события всех компонентов, и чтобы каждый метод в этом классе выполнял обработку событий? "

Пример:

class MyEventListener { //pseudo code [no constructors, etc]

    public void handleSubmitFormBtn(Event e) {

    }

    //other methods go here handling events from other swing components
}

Примечание: я не уверен насчет сигнатуры метода, но надеюсь, что вы поняли.

Вывод: ОДИН метод для обработки событий, инициируемых компонентами колебания ... возможно ли это? Является ли создание ОДНОГО класса для каждого события единственным способом? Не могу ли я перенаправить обработку событий на конкретные методы для одного класса?

Ответы [ 6 ]

4 голосов
/ 21 марта 2009

В Swing вы обычно используете анонимный класс для обработки ваших событий, например:

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

Хотя в принципе вы можете иметь один класс, обрабатывающий все ваши события, и зарегистрировать его для всех обработчиков, анонимные классы, как упоминалось выше, являются правильной идиомой для обработки событий.

Вы можете найти гораздо больше информации @ http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html

2 голосов
/ 21 марта 2009

У вас есть несколько вариантов, каждый со своими конкретными преимуществами / недостатками.

анонимные внутренние классы

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

1 голос
/ 21 марта 2009

Это можно сделать, создав прослушиватель с одним действием, который затем переключается в зависимости от источника входного сигнала, например что-то вроде:

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

Но это не рекомендуемый способ сделать это по разным причинам. Почему у вас есть проблема с созданием слушателя для каждого события, которое будет получено? Это модель Java для обработки событий пользовательского интерфейса, и если кто-то еще использует ваш код или вы когда-либо будете использовать чужой код, то этого вполне ожидаемо.

0 голосов
/ 30 декабря 2013

Платформа Melasse позволяет склеивать компонент пользовательского интерфейса с моделью без создания класса (даже анонимного) с синтаксисом Binder.bind(/* source, target, options */).

Например, не новый класс необходим для включения действия / кнопки, только когда в текстовом поле присутствует некоторый текст: https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value. То же самое для отображения / скрытия информации или метки ошибки.

Поддерживается большинство компонентов пользовательского интерфейса, все компоненты Java Bean (с поддержкой изменения свойств).

0 голосов
/ 21 марта 2009

Концептуальным решением было бы внедрение ОБРАЗЦА НАБЛЮДАТЕЛЯ.

0 голосов
/ 21 марта 2009

Вы можете иметь один класс, у которого есть методы слушателя многих событий:

class EventHandler implements ActionListener, ..., MouseListener {
   // implementation
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...