Buscar

Aula 12A - LPG

Prévia do material em texto

AULA 12A - CCT0024 – Linguagem de Programação 
 
 
Objetivos 
 
 Recordando... 
Na aula passada, vimos como criar uma interface gráfica usando componentes do pacote 
Swing para entrada de dados (JTextField e JPasswordField) pelo teclado e mouse (JButton). 
Nesta aula veremos como tratar eventos associados aos componentes gráficos. 
Eventos 
 
Evento é um acontecimento relevante no meio externo ao sistema relevante. Pode ser 
considerado como o resultado da interação do usuário com algum componente 
GUI. Mover o mouse, clicá-lo, digitar num campo de texto, selecionar um item de 
menu, fechar uma janela, clicar num botão, etc. são interações que enviam eventos 
para o programa, normalmente realizando serviços. 
Eventos também podem ser gerados em resposta a modificações do ambiente. Em 
outras palavras, define-se eventos GUI como mensagens (chamadas a métodos) que 
indicam que o usuário do programa interagiu com um dos componentes GUI. 
Um sistema orientado a objetos é definido como um conjunto de objetos interagindo 
ou trocando mensagens. Os eventos representam as ações dos atores neste processo ou 
alguma resposta a uma mudança de estado. 
 
Tratamento de Eventos 
 
Quase todos os componentes propagam eventos. Estes eventos devem ser tratados em 
algum ponto do código da aplicação. Os eventos nunca são tratados no próprio 
componente (dado que não se tem acesso ao código do componente). Para ligar o 
código do tratamento de eventos ao componente existem, no Java, um conjunto de 
interfaces chamadas listeners. Um listener é uma interface que especifica os métodos 
que uma aplicação deve ter para ser notificada da ocorrência de um determinado 
evento. Os componentes que geram eventos permitem que sejam adicionados ou 
removidos listeners em qualquer altura. 
 
 
 
 
 
 Introduzir o conceito de evento 
 Compreender o funcionamento do tratamento de eventos 
 Introduzir mais alguns componentes de interfaces gráficas 
 Tratar eventos de diferentes componentes gráficos 
 
 
 
O modelo de eventos do Java funciona da seguinte forma: 
 
 O componente que produz eventos possui métodos especiais do tipo 
addXXListener(XXListener) que permite adicionar ou remover 
listeners. XX representa o nome do evento. O método 
addXXListener recebe por parâmetro o objeto que implementa a 
interface XXListener; 
 A implementação do método addXXListener no componente 
apenas adiciona o objeto passado por parâmetro a uma lista interna. 
Sempre que ocorrer um evento (ex. botão pressionado), o 
componente percorre a lista e invoca, para cada elemento, o método 
definido na interface XXListener. 
 
No exemplo seguinte é construída uma GUI simples com um botão e uma 
caixa de texto. Sempre que o botão é pressionado a aplicação deve 
escrever na caixa de texto um número inteiro aleatório. Para processar os 
eventos é necessário analisar os eventos que o botão produz. É preciso 
saber que sempre que um botão é pressionado é criado um evento do tipo 
ActionEvent. 
Para adicionar listeners, a classe que representa o botão (JButton) possui 
um método chamado addActionListener que recebe por parâmetro um 
objeto que implemente a interface ActionListener. Na API vê-se que a 
interface ActionListener especifica um método chamado 
actionPerformed. 
 
Resumindo: 
 ActionEvent – evento gerado pelo botão quando pressionado. 
Sempre que o botão for pressionado, este irá percorrer a sua lista 
interna de listeners, chamando para cada um, o método 
actionPerformed; 
 ActionListener– interface que especifica os objetos que tratam 
eventos do tipo ActionEvent; Existem várias soluções possíveis 
para tratar o evento: 
 
 Recorrendo à própria classe (GUI) – a aplicação gráfica tem de 
implementar os listeners necessários; 
 
 Recorrendo a classes locais – é criada uma classe local que 
implementa os listeners necessários; 
 
 Recorrendo a classes internas – é criada uma classe dentro da GUI. 
A classe interna implementa os listeners necessários; 
 
 Recorrendo a classes anônimas – criam-se classes anônimas que 
implementem os listeners dos eventos a tratar. As classes 
anônimas são classes internas especiais; 
 
A seguir apresenta-se cada uma das soluções. 
 
 
 
 
 
 
 
Utilizando a própria classe 
 
import javax.swing.*; 
import java.awt.BorderLayout; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.util.Random; 
 
public class EventosGUI_1 extends JFrame implements ActionListener { 
 
 private JTextField texto; 
 private JButton bCriar, bApagar; 
 private Random gerador; 
 
 public static void main(String[] args) { 
 EventosGUI_1 gui = new EventosGUI_1("Tratamento eventos na 
própria classe"); 
 } 
 
 public EventosGUI_1(String titulo) { 
 super(titulo); 
 gerador =new Random(); 
 adicionaComponentes(); 
 /* Faz com que a janela seja dimensionada para caber os seus 
subcomponentes.*/ 
 pack(); 
 setVisible(true); 
 } 
 
 private void adicionaComponentes() { 
 // Cria um painel onde irá guardar os componentes 
 JPanel painelPrincipal = new JPanel(); 
 // Adiciona uma legenda 
 JLabel label = new JLabel("Número aleatório: "); 
 painelPrincipal.add(label); 
 // Adiciona o campo de texto com 20 colunas 
 // O campo de texto não pode ser editado 
 texto = new JTextField(20); 
 texto.setEditable(false); 
 painelPrincipal.add(texto); 
 // Adiciona um botão que cria o número 
 bCriar = new JButton("Criar"); 
 painelPrincipal.add(bCriar); 
 // Adiciona um botão que apaga o número 
 bApagar =new JButton("Apagar"); 
 painelPrincipal.add(bApagar); 
 // Adiciona o painel principal à JFrame 
 getContentPane().add(painelPrincipal, BorderLayout.CENTER); 
 // Código para tratar os eventos 
 // Como o tratamento é na própria classe basta adicionar como 
Listener a própria instância (this) 
 bCriar.addActionListener(this); //COmo já foi visto, ele adiciona a 
si próprio 
 bApagar.addActionListener(this); 
 } 
 // Método definido na interface ActionListener 
 public void actionPerformed(ActionEvent evt){ 
 // Determina quem lançou o evento 
 if (evt.getSource() == bCriar){ 
 
 // Cria o número aleatório 
 texto.setText(String.valueOf(gerador.nextInt())); 
 } 
 else if (evt.getSource() == bApagar){ 
 // Apaga o número previamente criado 
 texto.setText(""); 
 } 
 } 
} 
 
 
 
Analisando o código acima, vê-se que é implementada a interface 
ActionListener. Isto é necessário porque o evento está sendo tratado na 
classe que representa a GUI. Ao indicar que a classe implementa a 
interface, será necessário implementar o método actionPerformed. Este 
método irá conter o código responsável pelo tratamento do evento. 
Contudo, para isto tudo funcionar é necessário que a classe diga que está 
interessada em receber eventos do botão. A classe declara que está 
interessada em receber eventos, invocando o método addActionListener 
do botão. A partir deste momento, sempre que o botão for pressionado, 
este chama o método actionPerformed da aplicação gráfica. 
 
Em resumo: 
Declara-se a implementação do listener apropriado (implements 
XXListener); 
Implementa-se o(s) método(s) do listener (a lista de métodos varia de 
evento para evento); 
Registra-se no componente (addXXlistener). 
 
 
 
Utilizando uma classe local 
 
A próxima listagem apresenta uma solução que utiliza uma classe 
externa, mas que é local à classe da aplicação gráfica. 
 
import javax.swing.*; 
import java.awt.BorderLayout; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent;import java.util.Random; 
 
public class EventosGUI_2 extends JFrame { 
 static final String APAGAR ="Apagar"; 
 static final String CRIAR = "Criar"; 
 private JTextField texto; 
 private JButton bCriar, bApagar; 
 private Random gerador; 
 
 public static void main(String[] args){ 
 EventosGUI_2 gui = new EventosGUI_2("Tratamento eventos 
numa classe local"); 
 
 } 
 
 public EventosGUI_2(String titulo) { 
 super(titulo); 
 gerador =new Random(); 
 adicionaComponentes(); 
 /* Faz com que a janela seja dimensionada 
 para caber os seus subcomponentes.*/ 
 pack(); 
 setVisible(true); 
 } 
 
 private void adicionaComponentes() { 
 // Cria um painel onde irá guardar os componentes 
 JPanel painelPrincipal = new JPanel(); 
 // Adiciona uma legenda 
 JLabel label = new JLabel("Número aleatório: "); 
 painelPrincipal.add(label); 
 // Adiciona o campo de texto com 20 colunas 
 // O campo de texto não pode ser editado 
 JTextField aux1 = new JTextField(20); 
 aux1.setEditable(false); 
 painelPrincipal.add(aux1); 
 // Adiciona um botão que cria o número 
 JButton aux2 = new JButton("Criar"); 
 aux2.setActionCommand(CRIAR); 
 painelPrincipal.add(aux2); 
 // Adiciona um botão que apaga o número 
 JButton aux3 = new JButton("Apagar"); 
 aux3.setActionCommand(APAGAR); 
 painelPrincipal.add(aux3); 
 // Adiciona o painel principal à JFrame 
 getContentPane().add(painelPrincipal,BorderLayout.CENTER ); 
 
 // Código para tratar os eventos 
 // 1 - Cria uma instância da classe local 
 // 2 - Registra a instância como Listener para cada botão 
 TrataEvento listener = new TrataEvento(aux1); 
 aux2.addActionListener(listener); 
 aux3.addActionListener(listener); 
 } 
} 
 
//--------------- Classe Local ------------------------ 
class TrataEvento implements ActionListener { 
 private JTextField texto; 
 private Random gerador; 
 TrataEvento(JTextField texto){ 
 this.texto = texto; 
 gerador =new Random(); 
 } 
 // Método definido na interface ActionListener 
 public void actionPerformed(ActionEvent evt) { 
 if(evt.getActionCommand().equals(EventosGUI_2.CRIAR)){ 
 texto.setText(String.valueOf(gerador.nextInt())); 
 } 
 else if(evt.getActionCommand().equals(EventosGUI_2.APAGAR)){ 
 texto.setText(""); 
 } 
 
 } 
} 
 
 
 
Em relação à abordagem anterior, utilizando uma classe local deixa-se de 
indicar que a interface gráfica implementa a interface ActionListener e 
deixa de ser necessário guardar o atributo referente à caixa de texto. Mas 
foi necessário criar uma classe local (não se coloca nenhum modificador) e 
guardar nessa classe a informação necessária para tratar o evento. 
Guarda-se uma referência para a caixa de texto onde escreve-se (passada 
no construtor) e cria-se um gerador de números aleatórios (deixou de 
pertencer à classe da aplicação gráfica). A classe local tem de implementar 
a interface ActionListener. Assim, o método actionPerformed passou 
para esta classe. A classe da aplicação gráfica apenas tem de criar uma 
instância da classe local e registrá-la nos botões que criou. A vantagem 
desta abordagem é que permite separar o código da aplicação gráfica do 
código que trata os eventos. 
 
 
Utilizando uma classe anônima 
 
A listagem seguinte apresenta uma solução que utiliza uma classe anônima 
para cada componente. 
 
import javax.swing.*; 
import java.awt.BorderLayout; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.util.Random; 
public class EventosGUI_4 extends JFrame { 
 static final String APAGAR ="Apagar"; 
 static final String CRIAR ="Criar"; 
 private JTextField texto; 
 private JButton bCriar, bApagar; 
 private Random gerador; 
 
 public static void main(String[] args){ 
 EventosGUI_4 gui = new EventosGUI_4("Tratamento eventos 
numa classe ANÔNIMA"); 
 } 
 
 public EventosGUI_4(String titulo) { 
 super(titulo); 
 gerador =new Random(); 
 adicionaComponentes(); 
 /* Faz com que a janela seja dimensionada para caber os seus 
subcomponentes.*/ 
 pack(); 
 setVisible(true); 
 } 
 
 private void adicionaComponentes() { 
 // Cria um painel onde irá guardar os componentes 
 
 JPanel painelPrincipal = new JPanel(); 
 // Adiciona uma legenda 
 JLabel label = new JLabel("Número aleatório: "); 
 painelPrincipal.add(label); 
 // Adiciona o campo de texto com 20 colunas 
 // O campo de texto não pode ser editado 
 final JTextField aux1 = new JTextField(20); 
 aux1.setEditable(false); 
 painelPrincipal.add(aux1); 
 
 // Adiciona um botão que cria o número 
 JButton aux2 = new JButton("Criar"); 
 aux2.setActionCommand(CRIAR); 
 painelPrincipal.add(aux2); 
 
 // Adiciona um botão que apaga o número 
 JButton aux3 = new JButton("Apagar"); 
 aux3.setActionCommand(APAGAR); 
 painelPrincipal.add(aux3); 
 
 // Adiciona o painel principal à JFrame 
 getContentPane().add(painelPrincipal,BorderLayout.CENTER ); 
 
 // 1 - Cria uma classe anônima que implemente a interface 
ActionListener 
 // 2 - Regista a instância como Listener do botão 
 // Nota: Os objetos utilizados no listener devem ser finais 
 final Random gerador = new Random(); 
 ActionListener anonimo1 =new ActionListener(){ 
 public void actionPerformed(ActionEvent evt){ 
 aux1.setText(String.valueOf(gerador.nextInt())); 
 } 
 }; 
 aux2.addActionListener(anonimo1); 
 
 ActionListener anonimo2 = new ActionListener() { 
 public void actionPerformed(ActionEvent evt) { 
 aux1.setText(""); 
 } 
 }; 
 aux3.addActionListener(anonimo2); 
 } 
} 
 
 
 
A utilização de classes anônimas para tratar os eventos pode parecer 
complexa e pouco clara. No entanto, esta abordagem é de longe a mais 
eficiente quando o código que trata o evento é pequeno ou quando 
possuímos muitos componentes. Apesar do exemplo anterior utilizar duas 
classes anônimas, nada impede que se utilize a mesma classe anônima 
para tratar os eventos de diversos componentes. A única restrição na 
utilização deste tipo de classes tem a ver com o fato de que todas as 
referências utilizadas dentro da classe têm de ser finais ou atributos da 
própria classe. 
 
As classes anônimas são muito utilizadas para implementar localmente 
interfaces. A sintaxe típica para a construção de uma classe deste tipo é a 
seguinte: 
 
<NomeDaInterface> <nomeDaInstânciaAnônima>= new 
<NomeDaInterface> { 
// implementação dos métodos da interface 
}; 
 
Diálogos Pré-definidos 
 
O Swing oferece um conjunto de diálogos simples pré-definidos para uso 
em interações breves com o usuário: 
 mensagens de erro, de alerta 
 obtenção de uma confirmação 
 entrada de um único campo de texto 
 
Classe JOptionPane 
 
Estrutura básica: 
 
 
 
MessageDialog 
 
Exibe uma mensagem e aguarda OK do usuário 
 
 
 
 
 
 
 
 
Exemplo de MessageDialog: 
 
import java.awt.Component; 
import javax.swing.*; 
package exemplos; 
/** 
 * 
 * @author Prof. Eduardo Pareto 
 */ 
public class Janela { 
 private static Component janela; 
 public static void main(String[] args){ 
 JOptionPane.showMessageDialog( 
 janela, "Cuidado com as Provas!","Linguagem de 
Programação",JOptionPane.WARNING_MESSAGE); 
 } 
} 
 
 
 
ConfirmDialog 
 
Exibe uma mensagem e obtém uma confirmação (YES/NO, 
OK/CANCEL) 
 Conjuntos de botões de opção(optionType): 
 JOptionPane.DEFAULT_OPTION 
 JOptionPane.YES_NO_OPTION JOptionPane.YES_NO_CANCEL_OPTION 
 JOptionPane.OK_CANCEL_OPTION 
 
 
Exemplo de ConfirmDialog: 
 
import java.awt.Component; 
import javax.swing.*; 
package exemplos; 
/** 
 * 
 * @author Prof. Eduardo Pareto 
 */ 
public class Janela { 
 private static Component janela; 
 public static void main(String[] args){ 
 int resp = JOptionPane.showConfirmDialog(janela, 
 "Você já estudou para as provas?", "Escolha uma 
opção",JOptionPane.OK_CANCEL_OPTION); 
 } 
} 
 
 
 
 
InputDialog 
 
Exibe uma mensagem e obtém um valor de entrada do usuário 
 Campo texto editável 
 Combo box 
 
Exemplo de InputDialog: 
 
import java.awt.Component; 
import javax.swing.*; 
package exemplos; 
/** 
 * 
 * @author Prof. Eduardo Pareto 
 */ 
public class Janela { 
 private static Component janela; 
 public static void main(String[] args){ 
String nome = JOptionPane.showInputDialog(janela, 
"Qual é o seu número de Matrícula", 
"Linguagem de Programação",JOptionPane.QUESTION_MESSAGE); 
 } 
}

Continue navegando