Eventos

1. Eventos em Java

Java utiliza um mecanismo especial para tratar eventos, em especial os causados por interações entre usuários e a GUI. Eventos são objetos de primeira classe em Java, sendo subclasses de java.util.EventObject e java.awt.AWTEvent.
A idéia central é permitir que a ocorrência de um mesmo evento possa causar reações distintas e independentes sobre diversos objetos de uma aplicação, de forma flexível, facilitando a expansão e modificação dos sistemas.
Objetos da GUI que podem gerar algum tipo de evento (por exemplo, um botão que pode ser clicado) mantêm uma lista particular de objetos ouvintes, interessados em serem notificados da ocorrência de seus eventos. A lista é alterada por iniciativa dos ouvintes, que enviam uma mensagem padronizada ao potencial gerador do evento, pedindo para ser registrado na sua lista. Esses objetos podem a qualquer momento também pedir para serem removidos da lista. Quando um evento ocorre (por exemplo, o botão é clicado) o botão, no caso, examina a sua lista de ouvintes, e envia a cada um uma mensagem padrão, passando como parâmetro uma instância de uma classe específica de eventos. Cada ouvinte deve ter implementado em sua classe um método para tratar essa mensagem padrão. Isso é assegurado por Java quando exige que todo objeto, para se registrar como ouvinte, deve implementar em sua classe uma interface apropriada que força que ele seja capaz de responder às mensagens geradas pelo evento.
O ouvinte pode assim examinar o parâmetro recebido na mensagem, identificar a origem e outras características do evento, e a partir daí executar as ações apropriadas.
No primeiro exemplo, o construtor registra o próprio painel como ouvinte dos “eventos de clicar” gerados pelos 3 botões. Isso é feito através das mensagens: addActionListener(this) enviadas para os 3 botões. Essa mensagem faz com que o painel seja incluído nas listas de ouvintes dos 3 botões.
Será mostrado mais adiante porque essa forma de programar não é recomendada (embora pareça mais simples).
Para que isso seja possível, a classe PainelBotoes precisa implementar a interface java.awt.event.ActionListener. Isso é necessário porque o argumento do método addActionListener() deve ser do tipo ActionListener. Confira isso examinando a classe JButton (na realidade esse método está definido na superclasse de JButton).
Essa interface tem a seguinte definição, que está na API do Java, no pacote java.awt.event :

public interface ActionListener {
   public void actionPerformed (ActionEvent e);
}

Ao se clicar um botão com o mouse, um evento da classe ActionEvent é gerado. Como o painel foi registrado como ouvinte desses eventos, ele recebe a notificação da ocorrência do evento na forma de uma mensagem para ele de nome actionPerformed(ActionEvent evt). O argumento da mensagem é um objeto da classe ActionEvent, e contém informação que permite identificar qual objeto gerou o evento. O método getSource() aplicado ao evento retorna o objeto que gerou o evento.

A programação orientada a eventos (Event-driven programming) consiste em fazer programas cuja
ordem de execução seja determina pela ocorrência destes eventos.
 Todo objeto pode ser notificado por um evento. Basta implementar a interface apropriada e então registrar estes métodos como um event listener do evento apropriado.

Na programação orientada a eventos, nós precisamos de um loop eterno que fica eternamente esperando por
uma entrada do usuário. Isto é feito no Java sem nosso conhecimento... Só pelo fato de uma GUI estar ativa, este pseudo-loop está rodando.
Quando um evento ocorre, o gerenciador de janelas (window manager) cria um evento e passa para um tratador de eventos definido pelo programador. Este processo é chamado de callback. No final das contas, nosso trabalho é definir os tratadores de eventos...


Os componentes Swing podem gerar vários tipos de eventos diferentes.
Alguns exemplos:
 Usuário clica em um botão - ActionListener
 Usuário fecha um frame  - WindowListener
 Usuário pressiona um botão do mouse - MouseListener
 Usuário move o mouse  MouseMotionListener
 Componentes se tornam visíveis -  ComponentListener


Cada evento é representado por um objeto que contém informações sobre este evento.
Event source: é quem gera o evento, normalmente um componente da GUI
Event listener:
- responde ao evento.
- pode ser qualquer classe Java que implemente a interface correta.
- Uma única fonte pode ter múltiplos listeners.
- Um único listener pode responder a múltiplas sources.

1.1. BÁSICO DO TRATAMENTO DE EVENTOS EM JAVA
Escreva uma classe que implemente a interface associada ao evento a ser tratada.
Normalmente, esta interface tem o nome do formato SomethingListener.
Exemplo: tratadores de eventos de janelas são WindowListener, e os de mouse,, MouseListener
1. Crie um objeto da classe que você definiu.
2. Registre o objeto que você criou como tratador de eventos de um determinado objeto usando o método apropriado. Normalmente, este método tem o formato addSomethingListener(listener)

1.2. ACTIONEVENTS
Tipo de evento mais simples e comum no Swing.
Representa um ação qualquer ocorrendo em um componente da GUI.
Criado por:
- cliques em botão
- mudanças em checkboxes
- cliques de menu
- digitar [Enter] em uma textbox
- etc.

1.3. HIERARQUIA DE EVENTOS EM JAVA
java.lang.Object
  +--java.util.EventObject
      +--java.awt.AWTEvent
         +--java.awt.event.ActionEvent
           +--java.awt.event.TextEvent
              +--java.awt.event.ComponentEvent
                  +--java.awt.event.FocusEvent
                     +--java.awt.event.WindowEvent
                        +--java.awt.event.InputEvent
                           +--java.awt.event.KeyEvent
                              +--java.awt.event.MouseEvent

1.4. ESPERANDO POR ACTIONEVENTS
Acrescente um listener ao componente.
O método listener apropriado será chamado quando o evento ocorrer (pro exemplo, quando o botão for clicado).
Para eventos de ação, use a classe ActionListener.

1.5. BÁSICO PARA OUVIR EVENTOS

 Para fazermos um tratador de eventos precisamos de três ações básicas:
1.  Especificar uma classe que implemente uma interface de listener:
      public class MyClass implements ActionListener {
2. Código que implemente métodos dentro da interface listener:
      public void actionPerformed(ActionEvent e) {
      ...//code that responds to the event... }
3. Executar um código que registre uma instância desta classes como um listener de um ou mais componentes:
      someComponent.addActionListener(instanceOfMyClass);


1.6. IMPLEMENTAÇÃO ENVOLVE TRÊS PASSOS:
1. Instanciar componentes da interface.
 Janelas, botões, campos de textos, etc.
2. Adicionar os componentes ao container
 Um container é um repositório para elementos gráficos. Os principais são: Window(JFrame e JDialog) e Panel.
3. Estabelecer o tratamento de eventos da interface
 Por ex., o que deve acontecer quando o usuário clica em um botão, ou se o usuário digita alguma coisa em um campo de
texto, etc.

1.7. ESCREVENDO UM ACTIONLISTENER
Precisa-se implementar a interface ActionListener, que especifica o método actionPerformed que deve ser implementado em na classe em questão.
Não interessa se a classe extender alguma outra classe.
 O código básico é o seguinte:
// Prints a message when the button is clicked.

public class MyActionListener implements ActionListener {
      public void actionPerformed(ActionEvent event) {
            System.out.println(“Event occurred!”);
      }
}


1.8. ESCREVENDO UM ACTIONLISTENER
Agora precisa-se associar o ActionListener ao elemento gráfico cujo evento de ação será tratado.

JButton button = new JButton(“button 1”);
MyActionListener listener = new MyActionListener();
button.addActionListener(listener);

 Quando o botão button for clicado, será mostrado a mensagem “Event occurred!” impressa.
 O método addActionListener existe em vários componentes (basicamente todos aqueles que podem ter um evento de ação associado).

1.9. ONDE COLOCAR UM ACTIONLISTENER
Pode-se colocar em uma classe interna:
public class Outer {
   private class Inner implements ActionListener {
      public void actionPerformed(ActionEvent event){
...
    }
}

public Outer() {
   JButton myButton = new JButton();
   myButton.addActionListener(new Inner());
   }
}


1.10. ONDE COLOCAR UM ACTIONLISTENER
Pode-se colocar em uma classe interna anônima:
public class Outer {
       public Outer() {
             JButton myButton = new JButton();
             myButton.addActionListener(
                   new ActionListener() {
                          public void actionPerformed(ActionEvent e) {
...
                          }
                  }
            );
      }
}

EXEMPLO

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GUIDemo extends JFrame implements ActionListener {

    protected int numCl = 0;
    protected JButton meuJButton = null;
    protected JLabel meuJLabel = null;

    public GUIDemo(String title) {
        super(title);
        initialize();
    }

    public GUIDemo() {
        this("Demonstrando eventos");
    }

    protected void initialize() {
        this.setSize(new Dimension(200, 75));
        meuJButton = new JButton("Clique em mim!");
        meuJButton.addActionListener(this);
        meuJLabel = new JLabel("Num. clicks=" + numCl);
        this.getContentPane().add(meuJButton, BorderLayout.NORTH);
        this.getContentPane().add(meuJLabel, BorderLayout.SOUTH);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        numCl++;
        meuJLabel.setText("Num Clicks:" + numCl);
    }
}

Esta classe não tem um método principal, logo, não pode ser executada.

1.11. EVENTO

Um evento é um acontecimento atómico de um dispositivo externo (ex: clicar num botão do mouse ou digitar caracter no teclado).
- As ações desencadeadas pelo evento são executadas através da chamada de um método específico, devendo o programador indicar o objeto ouvinte (listener) que fica à espera do evento.
- Classes de manipulação dos eventos devem importar importjava.awt.event.*;

Swing define 10 tipos de eventos, gerados por componentes:
– ActionEvent(componentes: Button, List, MenuItem)
– AdjustmentEvent (componente: Scrollbar)
– ComponentEvent (componentes: Choice, Component)
– ContainerEvent (componente: Container)
– FocusEvent (componente: Component)
– ItemEvent (componentes: CheckBox, List)
– KeyEvent (componente: Component)
– MouseEvent (componente: Component)
– TextEvent (componente: TextComponent)
– WindowEvent (componente: Window)

O objeto à espera deve implementar uma interface, que depende do tipo de evento gerado:

Evento Interface Método
ActionEvent ActionListener actionPerformed()
AdjustmentEvent AdjustmentListener adjustmentValueChanged()
ComponentEvent ComponentListener componentHidden()
componentMoved()
componentResized()
componentShown()
ContainerEvent ContainerListener componentAdded()
componentRemoved()

JComponent

Método
Descrição
getName( )
Retorna o nome do componente
setName(String n)
Atribui um nome ao componente
getParent( )
Retorna o Container onde o componente getParent( ) foi adicionado
setVisible(boolean b)
Torna o componente visível ou não, de acordo com o parâmetro.
isShowing( )
Retorna true se o componente for visível e estiver dentro de um outro componente que está sendo mostrado
isEnabled( )
Determina se um componente está habilitado para receber a entrada do usuário e gerar eventos.
setEnabled(boolean b)
Habilita ou desabilita o componente.
setToolTipText(String text)
Registra o texto para ser mostrado em tooltip
setPreferredSize(Dimension d)
Atribui o tamanho desejado
getPreferredSize()
Retorna o tamanho do componente.

Container

Método
Descrição
add(Component c)
Adiciona um componente ao container.
add(Component c, int i)
Adiciona um componente ao container na posição indicada pelo segundo parâmetro.
getAlingnmentX()
Retorna um inteiro correspondente ao alinhamento no eixo x.
getAlingnmentY()
Retorna um inteiro correspondente ao alinhamento no eixo y.
removeAll( )
Remove todos os componentes inseridos.
setLayout(LayoutManager l)
Reorganiza o container e todos os seus componentes.


Tratamento de Eventos

Categotia
Interface
Métodos
Método do Componente
JButton, JLabel, JList, JMenu, JTexField
ActionListener
actionPerformed
(ActionEvent)
addActionListener
(ActionListener)
JCheckBox, JCheckboxMenuItem
Choice, JLabel
ItemListener
itemStateChanged
(ItemEvent)
addItemListener
(ItemListener)
Capturar teclas digitadas
KeyListener
keyPressedkey
Released
keyTyped
(KeyEvent)
addKeyListener
(KeyListener)
Tratar eventos de pressionar o mouse
MouseListener
mousePressed
mouseReleased
mouseEntered
mouseExited
mouseClicked
(MouseEvent)
addMouseListener
(MouseListener)
Tratar eventos de movimentação do
mouse
MouseMotion
Listener
mouseDragged
mouseMoved
(MouseEvent)
addMouseMotion
Listener
(MouseMotionListener)
JTextArea
JTextField
TextListener
textValueChanged
(TextEvent)
addTextListener
(TextListener)
JFrames
WindowListener
windowClosing
windowOpened
windowIconified
windowDeiconified
windowClosed
windowActivated
windowDeactivated
(WindowEvent)
addWindowListener
(WindowListener)


- Um botão é uma instância de JButton.
- No AWT/Swing, a classe implementa a interface ActionListener, e o método actionPerformed processa o evento:



1.12. Forma de um objecto tratar, no Swing, um evento ActionEvent:

1. Implementar interface ActionListener
   class MyClass implements ActionListener{
2. Dentro da classe definir o método: 
             void actionPerformed(ActionEvent e) {
            // código de reacção ao evento
            }
}
3. Adicionar, no botão, o objecto que processa o evento

void addActionListener(ActionListener l)

Exemplo:

Classe SwingApplication.java

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

public class SwingApplication {

    private int numClicks  = 0;
    private JLabel label  = new JLabel("Buttonclicks: " + numClicks);
    private JButton button  = new JButton("Pressme!");

    public SwingApplication(JPanel jp) {
        jp.add(label);
        jp.add(button);
        button.addActionListener(new Handler());
    }

    private class Handler implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            numClicks++;
            label.setText("Buttonclicks: " + numClicks);
        }
    }
}


Classe Main.java

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

public class Main {

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Counter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel p = new JPanel();
        frame.setContentPane(p);
        SwingApplication app = new SwingApplication(p);
        frame.pack();
        frame.setVisible(true);
    }
}

Execução da classe Main.java:

Efetuando 10 (dez) clique no botão Pressione-me!


Exemplo de evento:


import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class ExemploAction extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private JButton botao1;
    private JButton botao2;
    private JTextArea editorStatus;
    private JScrollPane scrollPane;

    public ExemploAction() {
        super();
        initGUI();
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final ExemploAction inst = new ExemploAction();
                inst.setLocationRelativeTo(null);
                inst.setVisible(true);
            }
        });
    }

    @Override
    public void actionPerformed(final ActionEvent arg0) {
        getEditorStatus().append(
                ((JButton) arg0.getSource()).getText() + " foi pressionado!\n");
    }

    private JButton getBotao1() {
        if (botao1 == null) {
            botao1 = new JButton();
            botao1.setText("Botão 1");
            botao1.addActionListener(this);
        }
        return botao1;
    }

    private JButton getBotao2() {
        if (botao2 == null) {
            botao2 = new JButton();
            botao2.setText("Botão 2");
            botao2.addActionListener(this);
        }
        return botao2;
    }

    private JTextArea getEditorStatus() {
        if (editorStatus == null) {
            editorStatus = new JTextArea();
            editorStatus.setAutoscrolls(true);
            editorStatus.setEditable(false);
            editorStatus.setEnabled(false);

        }
        return editorStatus;
    }

    private JScrollPane getScrollPane() {
        if (scrollPane == null) {
            scrollPane = new JScrollPane();
            scrollPane.setViewportView(getEditorStatus());
        }
        return scrollPane;
    }

    private void initGUI() {
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        setLayout(new GridBagLayout());
        final GridBagConstraints constraints = new GridBagConstraints(0, 0, 1,
                1, 0.1, 0.1, GridBagConstraints.PAGE_START,
                GridBagConstraints.NONE, new Insets(10, 3, 3, 3), 0, 0);

        add(getBotao1(), constraints);
        constraints.gridx = 1;
        add(getBotao2(), constraints);
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 2;
        constraints.weighty = 1.0;
        constraints.fill = GridBagConstraints.BOTH;
        constraints.anchor = GridBagConstraints.CENTER;
        add(getScrollPane(), constraints);

        setSize(400, 300);
        getEditorStatus().append("Programa iniciado!\n");
    }
}

run:





Exemplo de execução de um evento:

Executando um código quando o usuário aperta um botão, apenas o botão 1 teve  um listener associado a ele, quando "pressionar botão 1" e ligar-se o evento associado a esse botão.

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

public class MyFrame extends JFrame {

    public static void main(String[] args) {
        new MyFrame();
    }

    public MyFrame() {
        super("Exemplo ActionListener");
        setSize(300, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container content = getContentPane();
        content.setLayout(new BorderLayout());
        JPanel painel = new JPanel(new FlowLayout());
        JButton botao1 = new JButton("Botao 1");
        painel.add(botao1);
        botao1.addActionListener(new MyButtonListener(this));
        painel.add(new JButton("Botao 2"));
        painel.add(new JButton("Botao 3"));
        content.add(painel, BorderLayout.SOUTH);
        content.add(new JScrollPane(new JTextArea()), BorderLayout.CENTER);
        painel = new JPanel(new FlowLayout());
        painel.add(new JLabel("Digite seu nome"));
        painel.add(new JTextField(10));
        String opcoes[] = new String[]{"Opção 1", "Opção 2", "Opção 3"};
        painel.add(new JComboBox(opcoes));
        content.add(painel, BorderLayout.NORTH);
        pack();
        setVisible(true);
    }

    private class MyButtonListener implements ActionListener {

        private JFrame parentComponent;

        MyButtonListener(JFrame parentComponent) {
            this.parentComponent = parentComponent;
        }

        public void actionPerformed(ActionEvent e) {
            JOptionPane.showMessageDialog(parentComponent, "BOTÃO 1 PRESSIONADO!");
        }
    }
}

run: