JavaRush /Курси /JAVA 25 SELF /Слухачі (Listeners) та інтерфейси подій

Слухачі (Listeners) та інтерфейси подій

JAVA 25 SELF
Рівень 50 , Лекція 0
Відкрита

1. Знайомство з подіями

У програмуванні подія — це сигнал про те, що щось сталося. Це може бути натискання кнопки, введення тексту, завершення завантаження даних, зміна значення змінної — усе, що може відбутися у вашому застосунку, та на що ви, як розробник, хочете відреагувати.

Якщо провести аналогію, то подія — це як дзвінок у двері: хтось прийшов, і ви вирішуєте, що робити далі. Ви можете відчинити двері, проігнорувати, зробити вигляд, що вас немає вдома, або навіть покликати всіх домашніх, щоб подивитися, хто це прийшов. У програмуванні подія — це «дзвінок», а ваша реакція — обробник події.

У Java події — це фундамент реактивного та графічного програмування (GUI). Без них не було б кнопок, випадних списків, віконних застосунків і навіть багатьох серверних систем.

Слухач (Listener): хто це і навіщо потрібен

Слухач (Listener) — це об’єкт, який підписується на певну подію і чекає, поки вона станеться. Щойно подія відбувається, слухач отримує сигнал і виконує заданий код реакції.

У Java слухачі зазвичай реалізуються через інтерфейси. Один із найпоширеніших прикладів — інтерфейс ActionListener. Його реалізують класи, які мають реагувати на дії користувача, наприклад натискання кнопки.

На практиці взаємодія будується так: є джерело події, наприклад кнопка, і є слухач — об’єкт, що реалізує потрібний інтерфейс. Джерело зберігає список усіх слухачів, які на нього підписані. Коли користувач натискає кнопку, джерело події викликає спеціальний метод у кожного зі слухачів.

Ця схема схожа на підписку на новини: доки ви підписані, вам надходитимуть сповіщення. У випадку з Java таким сповіщенням є виклик методу слухача, який виконує заздалегідь описані дії.

2. Інтерфейси подій: ActionListener, MouseListener та інші

У Java для кожного типу подій є свій інтерфейс слухача:

Тип події Інтерфейс слухача Де використовується
Дія
ActionListener
Кнопки, меню, таймери
Миша
MouseListener
Компоненти, що реагують на мишу
Клавіатура
KeyListener
Текстові поля, будь-які компоненти
Зміна
ChangeListener
Слайдери, чекбокси, моделі даних
Документ
DocumentListener
Зміни в тексті (наприклад, JTextField)

Кожен такий інтерфейс визначає один або кілька методів, які потрібно реалізувати. Наприклад, ActionListener вимагає реалізувати метод actionPerformed(ActionEvent e).

Приклад: ActionListener

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Кнопку було натиснуто!");
    }
}

3. Принцип роботи подійної моделі

Уся подійна модель Java будується на простому, але потужному механізмі:

  1. Джерело події (наприклад, кнопка) підтримує список слухачів.
  2. Коли відбувається якась дія (наприклад, користувач натискає кнопку), джерело створює об’єкт події (наприклад, ActionEvent).
  3. Джерело обходить усіх зареєстрованих слухачів і викликає в них відповідний метод (наприклад, actionPerformed), передаючи об’єкт події.
  4. Кожен слухач сам вирішує, що робити з цією подією.

Схема роботи подій:

flowchart LR A[Користувач натиснув кнопку] --> B[Кнопка створила подію] B --> C[Кнопка викликає actionPerformed у всіх слухачів] C --> D[Слухач реагує: виконує свій код]

Приклад коду:

import javax.swing.*;

public class EventDemo {
    public static void main(String[] args) {
        JButton button = new JButton("Натисни мене!");

        button.addActionListener(new MyActionListener());

        JFrame frame = new JFrame("Приклад події");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(button);
        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

Коли користувач натискає кнопку, метод actionPerformed у всіх слухачів спрацьовує.

4. Приклад: додавання слухача до кнопки

Розберімо класичну схему на простому прикладі.

Крок 1. Створюємо кнопку

JButton button = new JButton("Сказати привіт");

Крок 2. Створюємо слухача

class HelloListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Привіт, світ!");
    }
}

Крок 3. Реєструємо слухача

button.addActionListener(new HelloListener());

Коротко: як це виглядає в коді

JButton button = new JButton("Сказати привіт");
button.addActionListener(new HelloListener());

5. Анонімні класи та лямбда-вирази: коротко й зручно

Анонімний клас

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Анонімний слухач: привіт!");
    }
});

Лямбда-вираз (Java 8+)

button.addActionListener(e -> System.out.println("Лямбда! Привіт!"));

Лямбда — це найлаконічніший спосіб додати слухача, якщо ваша реакція на подію — один–два рядки.

6. Як це пов’язано з вашим застосунком?

Давайте інтегруємо цей механізм у ваш навчальний застосунок. Наприклад, у нас є просте вікно з кнопкою «Додати завдання». Під час натискання кнопки ми хочемо додати нове завдання до списку й вивести повідомлення.

Приклад коду:

import javax.swing.*;
import java.awt.event.ActionListener;

public class TaskManagerGUI {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Менеджер завдань");
        JButton addButton = new JButton("Додати завдання");

        // Використовуємо лямбду як слухача
        addButton.addActionListener(e -> {
            System.out.println("Завдання додано!");
            // Тут могла б бути логіка додавання завдання до списку
        });

        frame.add(addButton);
        frame.setSize(300, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Тепер ваш застосунок не просто виконує інструкції, а «реагує» на дії користувача!

7. Типові помилки під час роботи зі слухачами та подіями

Помилка № 1: забули зареєструвати слухача. Якщо ви створили слухача, але не додали його до джерела події, ваш код ніколи не буде викликано. Це як підписатися на журнал, але не надіслати заявку — журнал не прийде.

Помилка № 2: зареєстрували того самого слухача кілька разів. Якщо ви випадково додали одного й того самого слухача кілька разів, обробник буде викликано стільки разів, скільки ви його додали. Іноді це корисно, але частіше — джерело дивних багів («чому моя функція спрацьовує тричі?!»).

Помилка № 3: забули видалити слухача. Якщо слухач більше не потрібен, але ви його не видалили, він продовжує залишатися в пам’яті. У довготривалих застосунках це може призвести до витоків пам’яті.

Помилка № 4: тривалі операції в обробнику події. Якщо ви виконуєте важку роботу прямо в обробнику (наприклад, завантажуєте дані з інтернету), інтерфейс «зависає», і користувач починає нервувати. Краще запускати важку роботу в окремому потоці.

Помилка № 5: необроблені винятки в обробнику слухача. Якщо у вашому обробнику стається виняток, він може «вбити» весь ланцюжок подій. Логуйте помилки та обробляйте винятки, щоб застосунок не падав.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ