ActionListener.actionPerformed: примеры (JAVA)

Примеры использования actionPerformed в Java
Раздел: События (EventListener)
ActionListener.actionPerformed(ActionEvent e): void

Описание метода actionPerformed

Метод actionPerformed - это единственный абстрактный метод интерфейса java.awt.event.ActionListener. Формальная сигнатура:

public void actionPerformed(ActionEvent e)

Этот метод вызывается средой событий при возникновении action-события. Типичные источники событий: кнопки (JButton), элементы меню (JMenuItem), таймеры (javax.swing.Timer) и другие компоненты, генерирующие команду действия.

Аргумент ActionEvent e предоставляет данные события. Полезные методы в ActionEvent:

  • Object getSource() - источник события (например, компонент);
  • String getActionCommand() - командная строка события, часто задается компонентом или Action;
  • int getID() - идентификатор типа события;
  • long getWhen() - время (в миллисекундах) генерации события;
  • int getModifiers() - модификаторы клавиш при событии (CTRL, ALT и т. п.).

Возвращаемое значение отсутствует - метод void. Исключения могут быть только непроверяемыми (например, RuntimeException), но выбрасывание их из обработчика приведет к прерыванию обработки события и возможным логам стека.

Важно: в Swing обработчики вызываются в потоке диспетчеризации событий (EDT). Длительные операции в actionPerformed блокируют интерфейс. Для тяжёлой работы рекомендуется применять фоновые потоки, SwingWorker или пулы задач и обновлять UI через SwingUtilities.invokeLater.

Короткие примеры применения

Пример 1: анонимный класс для JButton

JButton btn = new JButton("Нажать");
btn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопка нажата: " + ((JButton)e.getSource()).getText());
    }
});
Кнопка нажата: Нажать

Пример 2: lambda (Java 8+)

JButton btn = new JButton("OK");
btn.addActionListener(e -> System.out.println("Команда: " + e.getActionCommand()));
Команда: OK

Пример 3: использование ActionListener с javax.swing.Timer

Timer timer = new Timer(1000, e -> System.out.println("Tick: " + System.currentTimeMillis()));
timer.setRepeats(true);
timer.start();
Tick: 1612345678901
Tick: 1612345679901
... (каждую секунду)

Пример 4: отдельный класс-обработчик

class MyAction implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action from: " + e.getSource());
    }
}

JButton b = new JButton("X");
b.addActionListener(new MyAction());
Action from: javax.swing.JButton[,0,0,0x0,invalid,layout=...]

Похожие интерфейсы в Java и особенности

  • javax.swing.Action - более богатый контракт для действий: имя, иконка, состояние enabled, краткая помощь. Удобен для объединения одной логики для нескольких компонентов.
  • AbstractAction - базовая реализация Action, наследование уменьшает шаблонный код.
  • ItemListener - используется для переключателей и чекбоксов, отслеживает изменение состояния элемента, а не «команду».
  • MouseListener/KeyListener - низкоуровневые события мыши и клавиатуры, применяются при необходимости подробного контроля ввода.

Выбор: для простых команд и кнопок подходит ActionListener. Если требуется объединять состояние и свойства действия между компонентами, предпочтительнее Action.

Аналоги в других языках и отличия

  • JavaScript (браузер): addEventListener. Колбэк получает объект события с полями и методами. Пример:
button.addEventListener('click', function(e) {
  console.log('Clicked, id=', e.target.id);
});
Clicked, id= btn1
  • Python (tkinter): обработчик указывается через аргумент command для Button или через bind для получения объекта события.
# tkinter
btn = Button(root, text='OK', command=lambda: print('Нажато'))
# или
widget.bind('', lambda e: print('Клик', e.x, e.y))
Нажато
Клик 12 8
  • C#: делегаты и события. Подпись обычно void Handler(object sender, EventArgs e). Пример:
button.Click += (s, ev) => Console.WriteLine("Click from " + ((Button)s).Text);
Click from OK
  • Kotlin: использование Java-API с возможностью SAM-конверсии и лямбд. Пример: button.addActionListener { e -> println(e.actionCommand) }.
  • Go: в GUI-библиотеках (fyne и т.п.) назначаются обработчики-функции, но язык чаще использует каналы и горутины для асинхронности.
  • PHP/SQL: в классическом исполнении событий интерфейса нет; в веб-клиенте используются JS. Серверные реакции реализуются через запросы HTTP, триггеры в SQL не эквивалент UI-событиям.
  • Lua: в игровых/GUI фреймворках применяются callback-функции, похожие по смыслу на actionPerformed.

Отличия от Java: система типов, поточная модель и контекст выполнения (браузер, GUI-фреймворк, сервер) влияют на детали API и требования к синхронизации.

Типичные ошибки и примеры

1) Долгая работа в обработчике, блокировка EDT

button.addActionListener(e -> {
    // длинная синхронная операция
    heavyComputation();
    label.setText("Готово");
});
Интерфейс замерзает пока выполняется heavyComputation()

Рекомендация: запускать тяжёлую работу в фоновом потоке, обновляя UI через SwingUtilities.invokeLater или SwingWorker.

2) Неправильное приведение типа источника события

public void actionPerformed(ActionEvent e) {
    JButton b = (JButton) e.getSource(); // ClassCastException, если источник не JButton
    System.out.println(b.getText());
}
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: ...

3) Забыли зарегистрировать слушатель

JButton btn = new JButton("X");
// btn.addActionListener(...) не вызван
При нажатии ничего не происходит

4) Захват переменных в лямбдах до Java 8 (неэффективно final)

int count = 0; // ошибка в анонимном классе до Java 8
btn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        count++; // нельзя, count должен быть final
    }
});
Компилятор: local variables referenced from an inner class must be final or effectively final

Изменения и совместимость

Сам интерфейс ActionListener и метод actionPerformed остаются стабильными долгое время. Значимые изменения коснулись платформы в целом:

  • Java 8 добавила возможность использования лямбд и ссылок на методы для SAM-интерфейсов, что значительно упростило код при добавлении слушателей.
  • Модульная система Java 9 ввела модуль java.desktop, включающий AWT/Swing; при использовании модулей требуется указание зависимостей.

API метода не менялся, обратная совместимость сохраняется.

Расширенные сценарии применения

Пример 1: запустить фон задачу через SwingWorker из обработчика

Пример java
btn.addActionListener(e -> {
    SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
        protected Void doInBackground() throws Exception {
            for (int i = 0; i <= 100; i += 10) {
                Thread.sleep(200);
                publish(i);
            }
            return null;
        }
        protected void process(List<Integer> chunks) {
            int last = chunks.get(chunks.size() - 1);
            progressBar.setValue(last);
        }
    };
    worker.execute();
});
Progress bar постепенно обновляется до 100 без блокировки UI

Пример 2: общий Action для нескольких кнопок

Пример java
Action saveAction = new AbstractAction("Сохранить") {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Сохраняется: " + e.getActionCommand());
    }
};
JButton b1 = new JButton(saveAction);
JMenuItem m1 = new JMenuItem(saveAction);
// при вызове с любой компоненты сработает одно действие
Сохраняется: Сохранить  (при выборе в меню или нажатии кнопки)

Пример 3: изменение набора слушателей во время выполнения

Пример java
ActionListener l = e -> System.out.println("One-time");
btn.addActionListener(l);
btn.addActionListener(e -> btn.removeActionListener(l));
// при первом нажатии выведется "One-time" и затем слушатель удалится
One-time
(после этого дальнейшие нажатия не выводят "One-time")

Пример 4: использование AtomicInteger для изменения счётчика в lambda

Пример java
AtomicInteger counter = new AtomicInteger(0);
btn.addActionListener(e -> System.out.println("Нажатий: " + counter.incrementAndGet()));
Нажатий: 1
Нажатий: 2
...

Пример 5: комбинирование таймера и действия для создания повторяющейся команды

Пример java
ActionListener task = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // e.getSource() вернет Timer при запуске по таймеру
        System.out.println("Событие от: " + e.getSource().getClass().getSimpleName());
    }
};
Timer t = new Timer(500, task);
t.start();
Событие от: Timer
Событие от: Timer
...

Пояснение: в сложных приложениях рекомендуется отделять логику работы от кода привязки к компонентам, использовать Action для переиспользования и фоновые механизмы для поддержания отзывчивости интерфейса.

джава ActionListener.actionPerformed function comments

En
ActionListener.actionPerformed Invoked when an action occurs