Baixe o app para aproveitar ainda mais
Prévia do material em texto
AULA 12 - 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 mais dois componentes (JCheckBox e JRadioButton ). Tratamento de eventos As tarefas que um aplicativo gráfico deve realizar são comandadas pelo usuário através da interação deste com a GUI. É comum clicar sobre um botão (“OK”, “Enviar” ou “Gravar”, por exemplo) para instruir o aplicativo a realizar uma tarefa. As aplicações com GUIs são, portanto, baseadas em eventos, que geralmente são gerados pelo usuário. Quando um usuário interage com um componente GUI, ele gera um evento, que resulta numa tarefa a ser executada. Alguns eventos comuns são o clicar em um botão, o digitar numa caixa de texto ou o selecionar uma opção de uma lista. O código que realiza uma tarefa em resposta ao evento é chamado de handler de evento, e o processo total de responder ao evento é conhecido como tratamento do evento. Tratando eventos de componentes Swing Vamos recordar dois componentes do pacote javax.swing que possuem eventos associados: JTextField e JPasswordField. A classe JTextField estende a classe JTextComponent (javax.swing.text), e possui recursos comuns aos componentes baseados em texto do Swing. Este componente serve, normalmente, para a entrada de dados. A classe JPasswordField estende JTextField adicionando métodos para o processamento de senhas. Este componente mostra “caracteres eco” à medida que o usuário digita, escondendo os caracteres digitados. Quando o usuário, após digitar um texto em um dos componentes acima, pressionar “Enter”, será gerado um evento que poderá acionar uma tarefa. Antes que um aplicativo possa responder a um evento, é necessário: 1. Criar uma classe que represente o handler do evento e instanciar um objeto dessa classe (o handler do evento). 2. Implementar uma interface apropriada, conhecida como interface listener de evento na classe do handler do evento; 3. Registrar o handler do evento, indicando que o objeto de handler do evento deve ser notificado quando o evento ocorrer. O componente GUI acionado pelo usuário gera um ActionEvent (pacote java.awt.event), que é processado pelo objeto handler do evento, que implementa uma interface ActionListener (pacote java.awt.event). 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 aplicativo a seguir utiliza as classes apresentadas para criar e manipular quatro campos de texto. Quando o usuário digita em um dos campos e pressiona “Enter”, o aplicativo exibe um caixa de diálogo com o texto digitado. Observe que o texto só pode ser digitado no componente que estiver sob “foco”. Um componente recebe o “foco” quando o usuário clica sobre ele ou quando “passeia” pelos objetos utilizando a tecla “tab”. import java.awt.FlowLayout; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JPasswordField; import javax.swing.JOptionPane; public class JanelaTexto extends JFrame{ private JTextField campo1; private JTextField campo2; private JTextField campo3; private JPasswordField campo4; public JanelaTexto(){ super("Testa caixas de texto"); setLayout(new FlowLayout()); // layout do frame campo1 = new JTextField(10); //caixa com 10 colunas add( campo1 ); // adiciona campo1 à janela campo2 = new JTextField("Campo editável"); add(campo2); campo3 = new JTextField("Não editável", 10); campo3.setEditable(false); // desativa edição add(campo3); campo4 = new JPasswordField("Senha",10); add(campo4); //instancia o objeto handler do evento TrataEvento handler = new TrataEvento(); campo1.addActionListener(handler);//registra handler campo2.addActionListener(handler);//registra handler campo4.addActionListener(handler);//registra handler } // fim do construtor // classe que implementa o objeto handler do evento private class TrataEvento implements ActionListener{ public void actionPerformed(ActionEvent evento){ String s = ""; if (evento.getSource() == campo1) s=String.format("Texto 1: %s",campo1.getText()); else if (evento.getSource() == campo2) s=String.format("Texto 2: %s",campo2.getText()); else if (evento.getSource() == campo4) s = String.format("Texto: %s", new String(campo4.getPassword())); JOptionPane.showMessageDialog(null, s); } } // fim da classe TrataEvento } // fim da classe JanelaTexto A largura em pixels de uma coluna de texto depende o tamanho da fonte atual do campo de texto. Se o texto digitado for mais largo que o campo de 10 colunas do objeto, a parte do texto à direita não ficará visível. O tratamento de eventos nesse exemplo é realizado por um objeto da classe TrataEvento. Quando o usuário pressionar “Enter” em um JTextField ou no JPasswordField, o componente gera um ActionEvent (pacote java.awt.event), que é processado por um objeto que implemente a interface ActionListener (pacote java.awt.event). Para que o evento no objeto GUI seja atendido é necessário registrar previamente o objeto handler no objeto GUI. Na classe acima, foi utilizado o método actionPerformed de um objeto de tratamento de evento. No caso, a origem dos eventos é o “Enter” nos campos de texto da janela e, quando isto ocorrer, o sistema cria um objeto ActionEvent único que contém informações sobre o evento que acabou de ocorrer, tais como a origem do evento e o texto do campo de texto e passa este objeto em uma chamada para o método actionPerformed do “ouvinte” de eventos, ou listener de eventos. O método getSource() da classe ActionEvent retorna uma referência à origem do evento e o método getActionCommand, da mesma classe, retorna o texto do campo de texto. A seguir temos a classe TestaJanelaTexto que utiliza a classe acima. import javax.swing.JFrame; public class TestaJanelaTexto { public static void main( String args[] ) { JanelaTexto jan = new JanelaTexto (); jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jan.setSize(250, 120); jan.setVisible(true); } } Tipos comuns de eventos Existem diferentes tipos de eventos em uma interface GUI. Ao ocorrer um evento, as informações sobre o evento são armazenadas em um objeto de uma classe que estende a classe AWTEvent. A hierarquia abaixo contém várias classes de eventos do pacote java.awt.event. Estes tipos de eventos são utilizados tantos em objetos AWT como Swing. Eventos específicos para objetos Swing são declarados no pacote javax.swing.event. Object EventObject AWTEvent ActionEvent AdjustmentEvent ItemEvent TextEvent ComponentEvent ContainerEvent FocusEvent PaintEvent WindowEvent InputEvent KeyEvent MouseEvent O modelo de tratamento que vimos aqui é conhecido como modelo de delegação de eventos, pois o processamento de um evento é passado a um objeto particular no aplicativo, o objeto listener ou o ouvinte de eventos. Para cada tipo de evento, existe uma interface ouvinte de eventos. Um ouvinte de evento é um objeto que implementa uma ou mais interfacesdo pacote java.awt.event ou javax.swing.event. Veja algumas interfaces na caixa ao lado. Cada interface ouvinte de eventos especifica os métodos de tratamento de evento que interessem. Quando ocorre um evento, o componente da interface com o qual o usuário interagiu informa seus ouvintes registrados, chamando o método de tratamento de evento adequado de cada ouvinte. Entendendo o funcionamento de eventos Registrando eventos Cada objeto JComponent, por exemplo JTextField, tem uma variável de instância chamada listenerList que referencia um objeto da classe EventListenerList do pacote javax.swing.event. Podemos entender listenerList como um array . Quando a instrução campo1.addActionListener (handler) é executada, uma nova entrada que contém uma referência ao objeto TextFieldHandler é colocada na listenerList do JTextField campo1. Ou seja, cada componente GUI mantém sua própria lista de ouvintes que foram registrados para tratar os eventos do componente. Chamando o handler de evento: Cada componente GUI suporta vários tipos de eventos: de mouse, de teclado, etc. Quando um evento ocorre, somente os métodos apropriados dos ouvintes de eventos são afetados. Cada tipo de evento tem uma ou mais interfaces ouvintes de eventos correspondentes. ActionEvents são tratados por ActionListeners, MouseEvents são tratados por MouseListeners e MouseMotionListeners, e KeyEvents são tratados por KeyListeners. Quando ocorre um evento, um componente GUI recebe da JVM um ID do evento que especifica o tipo de evento. O componente GUI utiliza o ID para decidir o tipo de ouvinte a ser acionado e o método a ser chamado no objeto ouvinte. Para que isto aconteça, é necessário registrar um handler de evento no componente GUI para o tipo particular de evento que seu aplicativo exige, e o componente GUI fará com que o método apropriado do handler seja chamado. WindowListener ActionListener AdjustmentListener ComponentListener ContainerListener FocusListener ItemListener KeyListener MouseListener MouseMotionListener TextListener Tratando evento de click em um botão Na aula passada vimos uma aplicação com JButton sem programar o tratamento de click. Vamos revisitar aquele exemplo acrescentando o tratamento do click no botão. A classe JanelaBotoes cria 2 JButtons com ícones, e realiza o tratamento de eventos dos botões em uma única instância da classe TrataBotao. import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JOptionPane; public class JanelaBotoes extends JFrame { private JButton botao1; private JButton botao2; public JanelaBotoes() { super("Testando Botões"); setLayout(new FlowLayout()); botao1 = new JButton("Botão simples"); add(botao1); Icon bug1 = new ImageIcon( getClass().getResource("bug1.gif")); Icon bug2 = new ImageIcon( getClass().getResource("bug2.gif")); botao2 = new JButton("Botão com ícone", bug1); botao2.setRolloverIcon(bug2); //icone de rollover add(botao2); TrataBotao handler = new TrataBotao(); botao2.addActionListener(handler); // registra handler botao1.addActionListener(handler); // registra handler } private class TrataBotao implements ActionListener{ public void actionPerformed(ActionEvent evento){ JOptionPane.showMessageDialog (JanelaBotoes.this, String.format("Você cliclou no : %s", evento.getActionCommand())); } } } Os components JButtons, assim como os JTextFields, geram ActionsEvents que podem ser processados por qualquer objeto ActionListener. A classe TrataBotao declara o método actionPerformed que exibe numa caixa de mensagem o rótulo do botão clicado pelo usuário. A classe TestaJanelaBotoes a seguir completa a aplicação. import javax.swing.JFrame; public class TestaJanelaBotoes{ public static void main(String args[]) { JanelaBotoes Jan = new JanelaBotoes(); Jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Jan.setSize( 300, 200 ); Jan.setVisible(true); } } As caixas de mensagens aparecem centralizadas na janela do aplicativo devido à chamada do método showMessageDialog, utilizar como primeiro argumento JanelaBotoes.this em vez de null. Este primeiro argumento indica o componente que irá conter (container) a caixa de diálogo. O botão de estado JCheckBox Os botões de estado JCheckBox e JRadioButton, descendentes do componente JToggleButton, trabalham com as informações de ativado (verdadeiro) ou desativado (falso). Um JRadioButton é diferente de um JCheckBox dado que vários JRadioButton quando agrupados são mutuamente exclusivos, ou seja, somente um dos JRadioButton pode estar selecionado por vez. A classe a seguir utiliza dois objetos JCheckBox para selecionar o estilo desejado de fonte do texto exibido em um JTextField, um para o estilo negrito, outro para o estilo itálico. Ao iniciar o aplicativo, nenhum dos JCheckBox estará ativado. import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JCheckBox; public class JanelaComCheckBox extends JFrame{ private JTextField texto; private JCheckBox cb1; private JCheckBox cb2; // construtor adiciona JCheckBoxes e JTextField public JanelaComCheckBox() { super( "Testa CheckBox" ); // cria JFrame com título setLayout( new FlowLayout() ); // define o layout texto = new JTextField("Fonte com novo estilo", 20); texto.setFont(new Font("Serif", Font.PLAIN,14)); add(texto); // adiciona textField ao JFrame cb1 = new JCheckBox( "Negrito" ); //CheckBox Negrito cb2 = new JCheckBox( "Italico" ); //CheckBox Itálico add(cb1); //adiciona CheckBox de negrito ao Frame add(cb2); //adiciona CheckBox de itálico ao Frame CheckBoxHandler h=new CheckBoxHandler();// cria handler cb1.addItemListener(h); //registra o mesmo handler p/.. cb2.addItemListener(h); //..os dois controles CheckBox } // fim do construtor // classe interna para tratar o evento ItemListener private class CheckBoxHandler implements ItemListener { // controla o estilo de fonte negrito private int valNegrito = Font.PLAIN; // controla o estilo de fonte itálico private int valItalic = Font.PLAIN; // responde aos eventos de caixa de seleção public void itemStateChanged(ItemEvent event) { // processa eventos da caixa de seleção de negrito if (event.getSource() == cb1) valNegrito = cb1.isSelected()?Font.BOLD:Font.PLAIN; // processa eventos da caixa de seleção de itálico if (event.getSource() == cb2) valItalic = cb2.isSelected()?Font.ITALIC:Font.PLAIN; // configura a fonte do campo de texto texto.setFont(new Font("Serif", valNegrito + valItalic, 14)); } // fim do método itemStateChanged } // fim da classe CheckBoxHandler } // fim da classe JanelaComCheckBox A classe TestaJanelaComCheckBox a seguir é utilizada para testar a classe anterior. import javax.swing.JFrame; public class TestaJanelaComCheckBox{ public static void main(String args[] ) { JanelaComCheckBox janela = new JanelaComCheckBox(); janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); janela.setSize(275, 100); //configura tamanho da janela janela.setVisible(true); // exibe a janela } // fim do main } O botão de estado JRadioButton O botão de opção, instância da classe JRadioButton, é parecido com a caixa de seleção apresentada, pois também tem dois estados, selecionado (verdadeiro) e não selecionado (falso). A classe a seguir utiliza botões que permitem que apenas um único estilo de fonte seja selecionado por vez. import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JRadioButton; import javax.swing.ButtonGroup; public class JanelaComRadioButton extends JFrame { private JTextField texto; private Font normalFont; private Font negritoFont; private Font italicoFont; private Font negrItalFont; private JRadioButton normalRB; private JRadioButton negritoRB; private JRadioButton italicoRB; private JRadioButton negrItalRB; // buttongroup para armazenar botões de opção private ButtonGroup grupoRB; // construtor adiciona JRadioButtons ao JFrame public JanelaComRadioButton() { super("Testa RadioButton" ); setLayout(new FlowLayout()); texto = new JTextField("Mudando o estilo", 25 ); add(texto); // adiciona textField ao JFrame // cria botões de opção normalRB = new JRadioButton("Normal",true); negritoRB = new JRadioButton("Negrito",false); italicoRB = new JRadioButton("Italico",false); negrItalRB = new JRadioButton("Negrito/Itálico",false); add(normalRB); // adiciona o botão do estilo normal add(negritoRB); // adiciona o botão de negrito add(italicoRB); // adiciona o botão de itálico add(negrItalRB);// adiciona botão de negrito/itálico // cria relacionamento lógico entre JRadioButtons grupoRB = new ButtonGroup(); // cria ButtonGroup grupoRB.add(normalRB); // adiciona botão ao grupo grupoRB.add(negritoRB); // adiciona botão ao grupo grupoRB.add(italicoRB); // adiciona botão ao grupo grupoRB.add(negrItalRB); // adiciona botão ao grupo // cria objetos fonte normalFont = new Font( "Serif", Font.PLAIN, 14 ); negritoFont = new Font( "Serif", Font.BOLD, 14 ); italicoFont = new Font( "Serif", Font.ITALIC, 14 ); negrItalFont = new Font( "Serif", Font.BOLD + Font.ITALIC, 14 ); texto.setFont(normalFont); // configura fonte inicial // registra eventos para JradioButtons normalRB.addItemListener( new RadioButtonHandler(normalFont)); negritoRB.addItemListener( new RadioButtonHandler(negritoFont)); italicoRB.addItemListener( new RadioButtonHandler(italicoFont)); negrItalRB.addItemListener( new RadioButtonHandler(negrItalFont)); }// fim do construtor RadioButtonFrame // classe interna para tratar eventos de botão de opção private class RadioButtonHandler implements ItemListener{ private Font font; // fonte associada com o listener public RadioButtonHandler(Font f) { font = f; // configura a fonte desse listener } // fim do construtor RadioButtonHandler // método de tratamento dos eventos de botão de opção public void itemStateChanged(ItemEvent event) { texto.setFont(font); // configura fonte de texto } // fim do método itemStateChanged } // fim da classe RadioButtonHandler interna e private } A classe TestaJanelaComRadioButton, a seguir, testa a classe anterior. import javax.swing.JFrame; public class TestaJanelaComRadioButton{ public static void main( String args[] ){ JanelaComRadioButton jan = new JanelaComRadioButton(); jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jan.setSize(300, 100); // define tamanho da janela jan.setVisible(true); // exibe a janela } // fim de main }
Compartilhar