CodeGym /Cursos /JAVA 25 SELF /Ouvintes (Listeners) e interfaces de eventos

Ouvintes (Listeners) e interfaces de eventos

JAVA 25 SELF
Nível 50 , Lição 0
Disponível

1. Introdução aos eventos

Em programação, um evento é um sinal de que algo aconteceu. Pode ser um clique de botão, entrada de texto, término do carregamento de dados, alteração do valor de uma variável — qualquer coisa que possa ocorrer no seu aplicativo e à qual você, como desenvolvedor, queira reagir.

Fazendo uma analogia, um evento é como o toque da campainha: alguém chegou, e você decide o que fazer em seguida. Você pode abrir a porta, ignorar, fingir que não está em casa ou até chamar todo mundo para ver quem chegou. Em programação, o evento é o “toque”, e sua reação é o manipulador de eventos.

Em Java, eventos são a base da programação reativa e da programação gráfica (GUI). Sem eles não haveria botões, listas suspensas, aplicativos de janela e até muitos sistemas de servidor.

Ouvinte (Listener): o que é e para que serve

Um ouvinte (Listener) é um objeto que se inscreve em um determinado evento e aguarda até que ele ocorra. Assim que o evento acontece, o ouvinte recebe um sinal e executa o código de reação definido.

Em Java, ouvintes geralmente são implementados por meio de interfaces. Um dos exemplos mais comuns é a interface ActionListener. Ela é implementada por classes que devem reagir às ações do usuário, como pressionar um botão.

Na prática, a interação funciona assim: há uma fonte do evento, por exemplo um botão, e há um ouvinte — um objeto que implementa a interface necessária. A fonte mantém uma lista de todos os ouvintes inscritos nela. Quando o usuário pressiona o botão, a fonte do evento chama um método especial em cada ouvinte.

Esse esquema é parecido com uma assinatura de notícias: enquanto você estiver inscrito, receberá notificações. No caso do Java, essa notificação é a chamada do método do ouvinte, que executa as ações previamente descritas.

2. Interfaces de eventos: ActionListener, MouseListener e outros

Em Java, para cada tipo de evento há uma interface de ouvinte:

Tipo de evento Interface do ouvinte Onde é utilizado
Ação
ActionListener
Botões, menus, temporizadores
Mouse
MouseListener
Componentes que reagem ao mouse
Teclado
KeyListener
Campos de texto, quaisquer componentes
Alteração
ChangeListener
Sliders, caixas de seleção, modelos de dados
Documento
DocumentListener
Mudanças no texto (por exemplo, JTextField)

Cada uma dessas interfaces define um ou mais métodos que precisam ser implementados. Por exemplo, ActionListener requer a implementação do método actionPerformed(ActionEvent e).

Exemplo: ActionListener

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

class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("O botão foi pressionado!");
    }
}

3. Princípio de funcionamento do modelo de eventos

Todo o modelo de eventos do Java é construído sobre um mecanismo simples, porém poderoso:

  1. A fonte do evento (por exemplo, um botão) mantém uma lista de ouvintes.
  2. Quando alguma ação acontece (por exemplo, o usuário clica no botão), a fonte cria um objeto de evento (por exemplo, ActionEvent).
  3. A fonte percorre todos os ouvintes registrados e chama neles o método correspondente (por exemplo, actionPerformed), passando o objeto do evento.
  4. Cada ouvinte decide por conta própria o que fazer com esse evento.

Esquema de funcionamento dos eventos:

flowchart LR
    A[Usuário clicou no botão] --> B[O botão criou o evento]
    B --> C[O botão chama actionPerformed em todos os ouvintes]
    C --> D[O ouvinte reage: executa seu código]

Exemplo de código:

import javax.swing.*;

public class EventDemo {
    public static void main(String[] args) {
        JButton button = new JButton("Clique em mim!");

        button.addActionListener(new MyActionListener());

        JFrame frame = new JFrame("Exemplo de evento");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(button);
        frame.setSize(200, 100);
        frame.setVisible(true);
    }
}

Quando o usuário clica no botão, o método actionPerformed de todos os ouvintes é disparado.

4. Exemplo: adicionando um ouvinte a um botão

Vamos analisar o esquema clássico em um exemplo simples.

Etapa 1. Criar o botão

JButton button = new JButton("Dizer olá");

Etapa 2. Criar o ouvinte

class HelloListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Olá, mundo!");
    }
}

Etapa 3. Registrar o ouvinte

button.addActionListener(new HelloListener());

Resumo: como isso fica no código

JButton button = new JButton("Dizer olá");
button.addActionListener(new HelloListener());

5. Classes anônimas e expressões lambda: curto e prático

Classe anônima

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Ouvinte anônimo: olá!");
    }
});

Expressão lambda (Java 8+)

button.addActionListener(e -> System.out.println("Lambda! Olá!"));

A lambda é a forma mais concisa de adicionar um ouvinte quando sua reação ao evento é de uma ou duas linhas.

6. Como isso se relaciona com o seu aplicativo?

Vamos integrar esse mecanismo ao seu aplicativo de estudo. Por exemplo, temos uma janela simples com o botão “Adicionar tarefa”. Ao clicar no botão, queremos adicionar uma nova tarefa à lista e exibir uma mensagem.

Exemplo de código:

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

public class TaskManagerGUI {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Gerenciador de tarefas");
        JButton addButton = new JButton("Adicionar tarefa");

        // Usamos uma lambda como ouvinte
        addButton.addActionListener(e -> {
            System.out.println("Tarefa adicionada!");
            // Aqui poderia estar a lógica de adicionar a tarefa à lista
        });

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

Agora seu aplicativo não apenas executa instruções, mas “reage” às ações do usuário!

7. Erros típicos ao trabalhar com ouvintes e eventos

Erro nº 1: esqueceu de registrar o ouvinte. Se você criou um ouvinte, mas não o adicionou à fonte do evento, seu código nunca será chamado. É como assinar uma revista, mas não enviar a solicitação — a revista não chegará.

Erro nº 2: registrou o mesmo ouvinte várias vezes. Se você adicionou o mesmo ouvinte várias vezes por engano, o manipulador será chamado tantas vezes quantas você o adicionou. Às vezes isso é útil, mas na maioria das vezes é fonte de bugs estranhos (“por que minha função dispara três vezes?!”).

Erro nº 3: esqueceu de remover o ouvinte. Se o ouvinte não é mais necessário, mas você não o removeu, ele continua ocupando memória. Em aplicativos de longa duração, isso pode levar a vazamentos de memória.

Erro nº 4: operações longas no manipulador de eventos. Se você faz um trabalho pesado diretamente no manipulador (por exemplo, baixa dados da internet), a interface “congela” e o usuário começa a ficar nervoso. É melhor executar o trabalho pesado em uma thread separada.

Erro nº 5: exceções não tratadas no ouvinte. Se ocorrer uma exceção no seu manipulador, ela pode “matar” toda a cadeia de eventos. Registre os erros (logging) e trate as exceções para que o aplicativo não caia.

1
Tarefa
JAVA 25 SELF, nível 50, lição 0
Bloqueado
Núcleo do módulo de comando da Starship 🚀
Núcleo do módulo de comando da Starship 🚀
1
Tarefa
JAVA 25 SELF, nível 50, lição 0
Bloqueado
Centro de Comando de Lançamento de Foguete ☄️
Centro de Comando de Lançamento de Foguete ☄️
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION