2010-03-12 7 views
4

Я только начал изучать, как использовать прослушиватели действий. В моем понимании это работает следующим образом:Каков общий способ программирования прослушивателей действий?

  1. Есть несколько классов, которые содержат «addActionListener» метод по умолчанию (например, классы для кнопок).

  2. Используя этот метод, мы добавляем к объекту прослушиватель действий. Например: listenedObject.addActionListener(listeningObject).

  3. Когда выполняется действие с «listenedObject», вызывается метод «actionPerformed» для «listenObject». Таким образом, это означает, что когда мы программируем класс для объекта listenObject, нам нужно поместить туда метод actionPerformed.

Что мне непонятно, должен ли мы создать новый класс для каждого объекта, который мы хотим слушать. Мне это не кажется элегантным решением. С другой стороны, если у нас есть один класс слушателя действий для всех (или хотя бы многих) объектов, то у нас есть проблема, поскольку экземпляр этого класса не будет знать, какой объект вызывает метод actionPerformed (и нам нужно что действия, выполняемые actionPerformed, различаются в зависимости от того, кто вызван для этого метода).

На мой взгляд, для каждого прослушанного объекта нам нужно создать «персональный» прослушиватель действий, и мы можем сделать это, установив определенное значение в соответствующее поле прослушивателя действий. Но я не уверен, что это стандартный способ пойти? Как обычно люди это делают?

ответ

7

Наиболее распространенный способ справиться с этим - судя по собственному личному опыту - это просто создать анонимный встроенный класс. Как это:

listenedObject.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent evt) { 
     // Your action handling code in here 
    } 
}); 

И часто я видел, как люди поместить вызов к методу объекта, содержащего listenedObject. Например, в диалоге, который имеет кнопку:

myOkayButton.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent evt) { 
     okayButtonPressed(); 
    } 
}); 

Затем позже в классе диалога:

private void okayButtonPressed() { 
    // Do what we need to do 
} 
+2

ОК. Понимаю. Кстати, что означает @Override? – Roman

+0

Или даже: public void actionPerformed (ActionEvent e) {onMyButtonClicked();} - почти указатель метода –

+1

@Override - это аннотация, это означает, что public void actionPerformed() переопределяет метод в своем суперклассе. Когда вы создаете встроенный анонимный класс, вы переопределяете ActionListener. Тебе просто не дано имя. –

2

Personnaly, когда это возможно, я предпочитаю использовать Action класс (в качестве примера подкласса из AbstractAction) вместо того, чтобы просто полагаться на прослушиватель действий. Таким образом, я могу предоставить получателю виджета имя, значок, всплывающую подсказку и т. Д. ...

2

Способ, которым я всегда считался полезным (для навигация) - создать анонимный внутренний класс, который затем делегаты внешнего класса:

listenedObject.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent evt) { 
     listenedObject_actionPerformed(evt); 
    } 
}); 


private void listenedObject_actionPerformed(ActionEvent evt) { 
    //Your handling goes here 
} 

Это то гораздо легче получить в код обработки в IDE, используя структурный поиск (CTRL + F12 в IDEA, CTRL + O в Eclipse).

Проблема с использованием одного класса (как GUI MyCoolPanel) в качестве общего слушателя на кучу из его компонентов (кнопок и т.д.), что метод actionPerformed тогда имеет много некрасивых if-else сравнений, чтобы выяснить какую кнопку на самом деле был нажат - не очень OO вообще!

Вы, безусловно, не должны слишком беспокоиться о характеристиках этого вида - они, вероятно, будут незначительными в экстремальных условиях! Преждевременная оптимизация - это класс Плохая вещь

0

Остерегайтесь того, что методы removeActionListener существуют по какой-либо причине. Вы можете пропускать прослушиватели, если объекты, которые вы слушаете, умрут с объектом, который обрабатывает события. Но если ваш компонент прослушивает модель, поставляемую из внешнего источника, вы должны добавить своих слушателей в addNotify и удалить их в методах removeNotify. В противном случае у вас может быть утечка памяти.

0

Может быть, это на самом деле не в данный момент, но я считаю, что в ближайшем будущем (после Java 7 выпуска) что-то, как это было бы обычным способом:

listenedObject.addActionListener (#{doSmth();}); 
1

Как я всегда находил полезным является для создания отдельного класса, который реализует интерфейс ActionListener и все другие методы, необходимые для выполнения действия. Таким образом, действие не привязано к определенному объекту и может быть запущено с помощью кнопки, меню и т. Д. Немного похоже на Command pattern. Он сохраняет код простым.

Анонимные классы не могут использоваться повторно.

Перенаправление объекта, содержащего listenedObject, приводит к гигантским классам, которые трудно поддерживать.

Смежные вопросы