Arquitetura de Tratamento de Eventos em Programas com GUI - Graphical User Interface Jorge H. C. Fernandes (jorge@dimap.ufrn.br) UFRN Abril de 2002
Programas com GUI Separação De Abstrações Arquitetura em Camadas Necessidade de Tratamento de Eventos Componentes de um Programa Baseado em Eventos Arquitetura de Um Programa com Interface Gráfica de Eventos Componentes Visuais (java.awt) e Seus Eventos Eventos e seus Observadores Observadores e Métodos de Notificação Layout Managers (Organizadores de Containers)
Separação de Abstrações Para que um programa seja construído de forma modular e manutenível é imprescindível a separação entre: modelo do sistema as chamadas regras de negócios Interface com usuário define a forma como o programa interage com o usuário e como as regras de negócios são ativadas
Arquitetura em Camadas Além dos módulos de Interface com o Usuário e Regras de Negócios, a grande maioria dos programas de suporte a sistemas de informações gerenciais ainda contém um módulo de Persistência (também chamado de Armazenamento/Recuperação de Dados) Estes três módulos são normalmente organizados em forma de camadas, conforme o esquema abaixo: Interface com o Usuário Regras de Negócio Persistência Em um esquema de camadas a interface interage apenas com as regras de negócio, e as regras de negócio interagem com a interface e com a camada de persistência
A Necessidade de Usar Tratamento de Eventos De modo diferente de um programa com interface baseada em textos (do tipo que usa comandos System.out.println e IO.readStr()), programas com interface gráfica oferecem uma vasta quantidade de alternativas de entrada de dados ao usuário. O usuário podem adotar um dentre vários caminhos possíveis, e o programador não consegue controlar o fluxo da mesma forma que o programa com interface textual. A solução usualmente adotada em programas modernos é construir a interação através do tratamento de eventos
Componentes de um Programa Baseado em Eventos Vários Componentes Visuais, também chamados de widgets aparecem na tela e capturam interação do usuário; Vários Eventos produzidos como resultado da interação do usuário com os componentes visuais, o que normalmente ocorre através do mouse e teclado; Um Despachante de Eventos organiza os eventos produzidos pelos componentes numa fila, que normalmente não é manipulada pelo programador Vários Observadores de Eventos, também chamados de listeners vários objetos que podem registrar o interesse por eventos específicos, conversando diretamente com os Componentes Visuais ou através do Despachante. Os observadores são notificados pelo despachante quando um evento de interesse ocorre e invocam um método específico sobre a Fachada; Uma Fachada das Regras de Negócio, um único objeto que tem por função receber as invocações dos observadores e executar a operação adequada
Arquitetura de um Programa com Interface Gráfica Componentes Visuais Regras de Negócio :Universidade :Curso :Curso :Curso :Aluno :Aluno :Aluno :Aluno :Aluno :Aluno :Aluno :Aluno :Aluno :Event :Event :Event :Event :Event :Event :Event Fachada invoca invoca invoca Produz eventos notifica notifica :EventDispatcher notifica :Event :Event Produz eventos Produz eventos :Event Listener :Event Listener :Event Listener
Componentes Visuais e Eventos que Produzem Componentes visuais notificam interessados sobre a ocorrência de interações, utilizando eventos Cada tipo (classe) de componente produz eventos específicos, dependendo do tipo de interação que oferece Um objeto da classe Button, por exemplo, informa a ocorrência de um click sobre ele através de um ActionEvent
Componentes Visuais do Package java.awt Component Button ScrollBar Canvas List CheckBox Choice Label Container TextComponent Panel Window TextField TextArea Frame Dialog
Quando Ocorrem os Principais Eventos? ActionEvent Usuário clica em um botão, pressiona return dentro de um textfield ou excolhe um item de menu WindowEvent Usuário fecha, minimiza, maximiza, etc., uma janela MouseEvent Usuário pressiona entra ou sai com o mouse de dentro um componente MouseMotionEvent Usuário move o mouse sobre um componente ComponentEvent Componente fica visível, é adicionado a um container FocusEvent Componente recebe o foco do teclado ItemEvent Seleção de uma tabela ou lista é modificada
A próxima figura mostra os tipos de eventos produzidos por cada classe, seja ela: Concreta (Frame, List, Button) ou Abstrata (Window, Container, Component, etc.)
Componentes Visuais e Eventos que Produzem Component EventObject Button ScrollBar AWTEvent Canvas List AdjustementEvent ActionEvent CheckBox Choice Label TextEvent ComponentEvent ItemEvent Container TextComponent ContainerEvent WindowEvent Panel Window TextField TextArea FocusEvent InputEvent PaintEvent Frame Dialog KeyEvent MouseEvent
Para cada tipo de evento existe um tipo de observador específico. Os vários tipos de observadores são chamados de listeners, e são especificados através de um contrato (interface). A próxima figura mostra uma hierarquia dos principais listeners do awt.
Principais Eventos java.awt e Seus Observadores (Listeners) EventListener EventObject ActionListener ItemListener AWTEvent AdjustementListener TextListener AdjustementEvent ActionEvent ComponentListener WindowListener TextEvent ComponentEvent ItemEvent ContainerListener MouseMotionListener ContainerEvent WindowEvent FocusEvent InputEvent PaintEvent KeyListener FocusListener MouseListener KeyEvent MouseEvent
Cada tipo de listener é notificado da ocorrência de eventos através da invocação de métodos (notificadores) sobre eles. Como um mesmo tipo de evento pode ser usado para várias finalidades, alguns listeners tem por obrigação implementar um ou mais métodos notificadores. A próxima figura mostra os principais tipos de listeners e seus métodos de notificação.
Observadores e seus Métodos de Notificação EventListener actionperformed(actionevent) adjustementvaluechanged(adjustementevent) componenthidden(componentevent) componentmoved(componentevent) ActionListener ItemListener componentresized(componentevent) componentshown(componentevent) itemstatechanged(itemevent) AdjustementListener TextListener textvaluechanged(textevent) windowactivated(windowevent) windowclosed(windowevent) ComponentListener WindowListener windowclosing(windowevent) windowdeactivated(windowevent) windowdeiconified(windowevent) windowiconified(windowevent) windowopened(windowevent) mousedragged(mouseevent) ContainerListener MouseMotionListener mousemoved(mouseevent) componentadded(containerevent) componentremoved(containerevent) focusgained(focusevent) focuslost(focusevent) mouseclicked(mouseevent) mouseentered(mouseevent) KeyListener FocusListener MouseListener mouseexited(mouseevent) mousepressed(mouseevent) mousereseased(mouseevent) keypressed(keyevent) keyreleased(keyevent) keytyped(keyevent)
Especificação de Alguns Listeners. Ver detalhes no pacote java.awt.event package java.awt.event; interface ActionListener { void actionperformed(actionevent evt); interface WindowListener { void windowactivated(windowevent evt); void windowclosed(windowevent evt); void windowclosing(windowevent evt); void windowdeactivated(windowevent evt); void windowdeiconified(windowevent evt); void windowiconified(windowevent evt); void windowopened(windowevent evt); interface ContainerListener { void componentadded(containerevent evt); void componentremoved(containerevent evt);
Trecho de Código para Tratamento de Eventos // 1 - Criando um componente visual Button b1 = new Button( Salvar"); // 2 - Criando um observador de Eventos através de uma classe anônima ActionListener observadordeb1 = new java.awt.event.actionlistener() { // 2.1 - implementando o método para receber uma notificação public void actionperformed(actionevent e) { // 2.1.1 - invoca o método da fachada System.out.println( O botão salvar foi pressionado! ); // 3 - Registrando um observador (listener) junto a um componente b1.addactionlistener(observadordeb1);
Um Cenário Usando Diagrama de Mensagens: Criando botão e tratador de eventos; interagindo, produzindo, despachando e tratando eventos :Object :EventDispatcher Criação dos Widgets e Tratadores de Eventos Button b1 = new Button( Salvar ); :Button ActionListener listener = new ActionListener() {... b1.addactionlistener(listener); :ActionListener <<usuário>> listeners.add(listener) click! Interagindo com Widgets e Produzindo Eventos ActionEvent evt = new ActionEvent(...); :ActionEvent Dispatcher.dispatchEvent(evt, listeners); [para todo listener em listeners] listener.actionperformed(evt); Despachando e Tratando Eventos System.out.println( O botão salvar foi pressionado );
É definido um adapter para cada listener cujo contrato (interface) é formado por mais de um método. Cada adapter fornece uma implementação vazia dos métodos da interface que implementa. O uso de adapters facilita a construção de tratadores de eventos, pois ao herdar de um adapter, o tratador só precisa implementar um subconjunto dos métodos da interface que necessita tratar.
actionperformed(actionevent) adjustementvaluechanged(adjustementevent) ComponentAdaper ContainerAdapter KeyAdapter FocusAdapter WindowAdapter MouseMotionAdapter MouseAdapter FocusListener MouseListener ComponentListener ContainerListener ActionListener AdjustementListener KeyListener WindowListener MouseMotionListener TextListener ItemListener EventListener componenthidden(componentevent) componentmoved(componentevent) componentresized(componentevent) componentshown(componentevent) itemstatechanged(itemevent) textvaluechanged(textevent) windowactivated(windowevent) windowclosed(windowevent) windowclosing(windowevent) windowdeactivated(windowevent) windowdeiconified(windowevent) windowiconified(windowevent) windowopened(windowevent) mousedragged(mouseevent) mousemoved(mouseevent) componentadded(containerevent) componentremoved(containerevent) focusgained(focusevent) focuslost(focusevent) mouseclicked(mouseevent) mouseentered(mouseevent) mouseexited(mouseevent) mousepressed(mouseevent) mousereseased(mouseevent) keypressed(keyevent) keyreleased(keyevent) keytyped(keyevent) Observadores, Adapters e Métodos de Notificação
Exemplo de Adapter: WindowAdapter Ver detalhes no pacote java.awt.event package java.awt.event; interface WindowListener { void windowactivated(windowevent evt); void windowclosed(windowevent evt); void windowclosing(windowevent evt); void windowdeactivated(windowevent evt); void windowdeiconified(windowevent evt); void windowiconified(windowevent evt); void windowopened(windowevent evt); class WindowAdapter implements WindowListener { void windowactivated(windowevent evt) {/* implementação vazia */ void windowclosed(windowevent evt) {/* implementação vazia */ void windowclosing(windowevent evt) {/* implementação vazia */ void windowdeactivated(windowevent evt) {/* implementação vazia */ void windowdeiconified(windowevent evt) {/* implementação vazia */ void windowiconified(windowevent evt) {/* implementação vazia */ void windowopened(windowevent evt) {/* implementação vazia */
Usando WindowAdapter import java.awt.frame; import java.awt.event.*; class UsandoWindowAdapter extends Frame { UsandoWindowAdapter() { this.settitle("usando um Window Adapter"); this.addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent evt) { System.exit(0); ); this.pack(); this.show(); public static void main(string[] args) { new UsandoWindowAdapter();
Não Usando WindowAdapter import java.awt.frame; import java.awt.event.*; class NaoUsandoWindowAdapter extends Frame { NaoUsandoWindowAdapter () { this.settitle("não Usando um Window Adapter"); this.addwindowlistener(new WindowListener() { public void windowclosing(windowevent evt) { System.exit(0); public void windowclosed(windowevent evt) { public void windowdeactivated(windowevent evt) { public void windowdeiconified(windowevent evt) { public void windowiconified(windowevent evt) { public void windowopened(windowevent evt) { public void windowactivated(windowevent evt) { ); this.pack(); this.show(); public static void main(string[] args) { new NaoUsandoWindowAdapter();
Para ler mais Java: Como Programar, Deitel & Deitel, Capítulos 12 e 13. The Life Cycle of a Java Event in JDK 1.1, by Roedy Green, 2002. http://mindprod.com/event11.html