CodeGym /Cursos /JAVA 25 SELF /Eventos no Swing e AWT: fundamentos e exemplos

Eventos no Swing e AWT: fundamentos e exemplos

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

1. Introdução muito breve ao Swing e ao AWT

Se o Java fosse um carro, então Swing e AWT seriam o seu “painel de instrumentos” e o “volante”. AWT (Abstract Window Toolkit) — a primeira biblioteca para criar aplicativos de janelas em Java. Ela usa os controles nativos do SO, portanto tem aparência diferente no Windows, Linux e Mac.

Swing — uma camada mais moderna sobre o AWT, escrita inteiramente em Java. O Swing é mais bonito, mais flexível, oferece um monte de recursos extras e tem a mesma aparência em todas as plataformas (bem, quase). Em ambos os casos, todos os elementos de interface (botões, campos de texto, checkboxes etc.) suportam trabalho com eventos.

Nesta aula usaremos o Swing: ele é mais simples para iniciantes e aparece com mais frequência em exemplos didáticos. Vamos entender como funciona o tratamento de eventos com o exemplo da tarefa mais popular — reagir ao clique de um botão.

Criando um botão

No Swing, um botão é criado assim:

JButton button = new JButton("Clique em mim!");

Aqui, “Clique em mim!” é o texto do botão.

Adicionando um ouvinte

Para reagir ao clique, é preciso registrar um ouvinte no evento:

button.addActionListener(new MyActionListener());

Mas o que é esse MyActionListener? É uma classe que implementa a interface ActionListener:

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

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

Quando o usuário clica no botão, o Swing chama o método actionPerformed de todos os ouvintes registrados via addActionListener.

Exemplo completo: janela simples com botão

Vamos juntar tudo e criar um aplicativo funcional:

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

public class SimpleButtonApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Exemplo de evento");
        JButton button = new JButton("Clique em mim!");

        // Adicionamos um ouvinte ao botão
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("O botão foi clicado!");
                JOptionPane.showMessageDialog(frame, "Oba! Botão clicado!");
            }
        });

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(button);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
}

O que está acontecendo aqui:

  • Criamos uma janela (JFrame).
  • Criamos um botão (JButton).
  • Adicionamos um ouvinte (classe anônima, para não criar arquivos separados).
  • Dentro de actionPerformed, imprimimos uma mensagem no console e mostramos uma janela pop-up (JOptionPane).
  • Adicionamos o botão na janela e exibimos a janela ao usuário.

Tente você mesmo copiar este código, executar — e clicar no botão!

2. Classes anônimas e expressões lambda

No código Java moderno, escrever classes separadas por causa de um único manipulador é como usar um tanque para ir comprar pão. É muito mais conveniente usar classes anônimas ou expressões lambda.

Classe anônima

Já vimos essa abordagem acima:

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // código de tratamento
    }
});

Aqui, a classe é declarada no próprio local, sem nome.

Expressão lambda (Java 8+)

Se a interface do ouvinte for funcional (ou seja, contiver apenas um método abstrato), você pode usar uma lambda:

button.addActionListener(e -> {
    System.out.println("Botão clicado via lambda!");
});

Ou até mais curto, se o corpo for de uma única linha:

button.addActionListener(e -> System.out.println("Lambda: botão clicado!"));

Isso não apenas reduz o código, como também o torna mais legível. Fato para os curiosos: a interface ActionListener é funcional porque tem apenas um método, actionPerformed.

4. Outros tipos de eventos

O mundo não se limita a botões! No Swing e no AWT, quase todo elemento de interface tem seus próprios eventos. Aqui estão os mais populares:

Eventos do mouse: MouseListener e MouseAdapter

Se você quiser reagir a cliques do mouse, use MouseListener:

button.addMouseListener(new MouseListener() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Clique do mouse no botão!");
    }
    // Os demais métodos podem ficar vazios
    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
});

Escrever cinco métodos vazios por causa de um único manipulador não é muito conveniente. Para isso existe o MouseAdapter:

button.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Clique do mouse no botão (via adaptador)!");
    }
});

MouseAdapter implementa todos os métodos da interface, e você sobrescreve apenas os necessários.

Eventos de teclado: KeyListener/KeyAdapter

Se você precisa capturar pressionamentos de tecla:

button.addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Tecla pressionada: " + e.getKeyChar());
    }
});

Eventos de alteração de texto: DocumentListener

Para campos de texto (JTextField, JTextArea) há ouvintes específicos:

JTextField textField = new JTextField();
textField.getDocument().addDocumentListener(new DocumentListener() {
    @Override
    public void insertUpdate(DocumentEvent e) {
        System.out.println("Texto alterado: " + textField.getText());
    }
    @Override public void removeUpdate(DocumentEvent e) {}
    @Override public void changedUpdate(DocumentEvent e) {}
});

Aliás, para a maioria dos eventos há adaptadores, para que você não precise escrever métodos vazios.

5. Prática: mini-exemplo com janela e botão

Vamos fazer um aplicativo GUI bem simples: uma janela com um botão que, ao ser clicado, incrementa um contador e exibe uma mensagem.

Exemplo: contador de cliques

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

public class ClickCounterApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Contador de cliques");
        JButton button = new JButton("Clique em mim!");
        JLabel label = new JLabel("Cliques: 0");
        // Contador de cliques (deve ser final ou efetivamente final)
        final int[] count = {0};

        button.addActionListener(e -> {
            count[0]++;
            label.setText("Cliques: " + count[0]);
        });

        frame.setLayout(new FlowLayout());
        frame.add(button);
        frame.add(label);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(250, 100);
        frame.setVisible(true);
    }
}

Explicação:

  • Criamos a janela, o botão e o rótulo para exibir o contador.
  • Usamos um array de um único elemento (final int[] count = {0};) para contornar a restrição de lambda a variáveis final/efetivamente final.
  • Cada vez que o botão é clicado, incrementamos o contador e atualizamos o texto do rótulo.

Ideia para prática: tente mudar a cor do botão a cada quinto clique!

6. Como o modelo de eventos funciona por dentro

Vamos dar uma olhada rápida sob o capô. Quando você chama:

button.addActionListener(listener);

o botão (objeto JButton) adiciona seu ouvinte a uma lista interna. Quando o usuário clica no botão, acontece o seguinte:

  1. O botão cria um objeto de evento (ActionEvent).
  2. O botão percorre a lista de ouvintes e chama em cada um o método actionPerformed.
  3. Seu manipulador executa as ações necessárias (por exemplo, atualiza o rótulo).

O principal a lembrar: cada evento pode ter qualquer quantidade de ouvintes — você pode adicionar vários manipuladores para um único botão; eles serão chamados em sequência.

7. Esquema visual: processamento de evento

graph TD
    A[Usuário clicou no botão] --> B{JButton}
    B --> C[Criar ActionEvent]
    C --> D[Chamar actionPerformed em todos os ouvintes]
    D --> E[O manipulador executa as ações]

7. Erros comuns ao trabalhar com eventos no Swing e no AWT

Erro nº 1: esqueceu de registrar o ouvinte. O botão não reage a cliques porque você esqueceu de chamar addActionListener.

Erro nº 2: trabalho pesado no manipulador. Se no manipulador você iniciar um laço demorado ou baixar algo da internet, a interface “congelará”. Para tarefas longas, use threads separados ou SwingWorker.

Erro nº 3: tentar alterar uma variável a partir da lambda sem final/efetivamente final. Dentro de uma lambda, você só pode usar variáveis final ou “efetivamente final”. Para contadores, use arrays ou classes específicas (AtomicInteger, se quiser algo mais profissional).

Erro nº 4: esqueceu de remover o ouvinte. Se você remove um componente, mas não remove o ouvinte, pode ocorrer vazamento de memória. Cancele as inscrições quando o componente não for mais necessário.

Erro nº 5: nem todos os métodos da interface foram implementados. Se você implementar, por exemplo, MouseListener diretamente, não se esqueça de todos os métodos! É melhor usar adaptadores (MouseAdapter, KeyAdapter).

1
Tarefa
JAVA 25 SELF, nível 50, lição 1
Bloqueado
Saudação na casa inteligente 🏡
Saudação na casa inteligente 🏡
1
Tarefa
JAVA 25 SELF, nível 50, lição 1
Bloqueado
Ativação do termostato 🌡️
Ativação do termostato 🌡️
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION