Universidade do Sul de Santa Catarina Linguagens de Programação II Disciplina na modalidade a distância Palhoça UnisulVirtual 2007 Linguagens de Programação II.indb 1 7/12/2006 13:59:04 Linguagens de Programação II.indb 2 7/12/2006 14:00:23 Apresentação Este livro didático corresponde à disciplina Linguagens de Programação II. O material foi elaborado visando a uma aprendizagem autônoma, abordando conteúdos especialmente selecionados e adotando uma linguagem que facilite seu estudo a distância. Por falar em distância, isso não significa que você estará sozinho. Não esqueça que sua caminhada nesta disciplina também será acompanhada constantemente pelo Sistema Tutorial da UnisulVirtual. Entre em contato sempre que sentir necessidade, seja por correio postal, fax, telefone, e-mail ou Espaço UnisulVirtual de Aprendizagem. Nossa equipe terá o maior prazer em atendê-lo, pois sua aprendizagem é nosso principal objetivo. Bom estudo e sucesso! Equipe UnisulVirtual. Linguagens de Programação II.indb 3 7/12/2006 14:00:23 Linguagens de Programação II.indb 4 7/12/2006 14:00:23 Andréa Sabedra Bordin Marcelo Medeiro Andrik Dimitrii Braga de Albuquerque Linguagens de Programação II Livro didático 2ª Edição revista e atualizada Design instrucional Flavia Lumi Matuzawa Leandro Kingeski Pacheco Palhoça UnisulVirtual 2007 Linguagens de Programação II.indb 5 7/12/2006 14:00:23 Copyright © UnisulVirtual 2007 Nenhuma parte desta publicação pode ser reproduzida por qualquer meio sem a prévia autorização desta instituição. 005.133 B72 Bordin, Andréa Sabedra Linguagem de programação II : livro didático / Andréa Sabreda Bordin, Marcelo Medeiro, Andrik Albuquerque ; design instrucional Flavia Lumi Matuzawa, Leandro Kingeski Pacheco. - 2 ed. revista e atualizada - Palhoça : UnisulVirtual, 2007. 334 p. : il. ; 28 cm. Inclui bibliografia. 1. Linguagem de programação (Computadores). 2. Java (Linguagem de programação de computador). I. Medeiro, Marcelo. II. Albuquerque, Andrik. III. Matuzawa, Flavia Lumi. IV. Pacheco, Leandro Kingeski. V. Título. Ficha catalográfica elaborada pela Biblioteca Universitária da Unisul Créditos Unisul - Universidade do Sul de Santa Catarina UnisulVirtual - Educação Superior a Distância Campus UnisulVirtual Rua João Pereira dos Santos, 303 Palhoça - SC - 88130-475 Fone/fax: (48) 3279-1541 e 3279-1542 E-mail: [email protected] Site: www.virtual.unisul.br Reitor Unisul Gerson Luiz Joner da Silveira Vice-Reitor e Pró-Reitor Acadêmico Sebastião Salésio Heerdt Chefe de gabinete da Reitoria Fabian Martins de Castro Pró-Reitor Administrativo Marcus Vinícius Anátoles da Silva Ferreira Campus Sul Diretor: Valter Alves Schmitz Neto Diretora adjunta: Alexandra Orsoni Campus Norte Diretor: Ailton Nazareno Soares Diretora adjunta: Cibele Schuelter Campus UnisulVirtual Diretor: João Vianney Diretora adjunta: Jucimara Roesler Equipe UnisulVirtual Administração Renato André Luz Valmir Venício Inácio Linguagens de Programação II.indb 6 Bibliotecária Soraya Arruda Waltrick Coordenação dos Cursos Adriano Sérgio da Cunha Ana Luisa Mülbert Ana Paula Reusing Pacheco Cátia Melissa S. Rodrigues (Auxiliar) Charles Cesconetto Diva Marília Flemming Itamar Pedro Bevilaqua Janete Elza Felisbino Jucimara Roesler Lilian Cristina Pettres (Auxiliar) Lauro José Ballock Luiz Guilherme Buchmann Figueiredo Luiz Otávio Botelho Lento Marcelo Cavalcanti Mauri Luiz Heerdt Mauro Faccioni Filho Michelle Denise Durieux Lopes Destri Moacir Heerdt Nélio Herzmann Onei Tadeu Dutra Patrícia Alberton Patrícia Pozza Raulino Jacó Brüning Rose Clér E. Beche Design Gráfico Cristiano Neri Gonçalves Ribeiro (coordenador) Adriana Ferreira dos Santos Alex Sandro Xavier Evandro Guedes Machado Fernando Roberto Dias Zimmermann Higor Ghisi Luciano Pedro Paulo Alves Teixeira Rafael Pessi Vilson Martins Filho Equipe Didático-Pedagógica Angelita Marçal Flores Carmen Maria Cipriani Pandini Caroline Batista Carolina Hoeller da Silva Boeing Cristina Klipp de Oliveira Daniela Erani Monteiro Will Dênia Falcão de Bittencourt Enzo de Oliveira Moreira Flávia Lumi Matuzawa Karla Leonora Dahse Nunes Leandro Kingeski Pacheco Ligia Maria Soufen Tumolo Márcia Loch Patrícia Meneghel Silvana Denise Guimarães Tade-Ane de Amorim Vanessa de Andrade Manuel Vanessa Francine Corrêa Viviane Bastos Viviani Poyer Logística de Encontros Presenciais Marcia Luz de Oliveira (Coordenadora) Aracelli Araldi Graciele Marinês Lindenmayr José Carlos Teixeira Letícia Cristina Barbosa Kênia Alexandra Costa Hermann Priscila Santos Alves Logística de Materiais Jeferson Cassiano Almeida da Costa (coordenador) Eduardo Kraus Monitoria e Suporte Rafael da Cunha Lara (coordenador) Adriana Silveira Caroline Mendonça Dyego Rachadel Edison Rodrigo Valim Francielle Arruda Gabriela Malinverni Barbieri Gislane Frasson de Souza Josiane Conceição Leal Maria Eugênia Ferreira Celeghin Simone Andréa de Castilho Vinícius Maycot Serafim Produção Industrial e Suporte Arthur Emmanuel F. Silveira (coordenador) Francisco Asp Projetos Corporativos Diane Dal Mago Vanderlei Brasil Secretaria de Ensino a Distância Karine Augusta Zanoni (secretária de ensino) Ana Paula Pereira Djeime Sammer Bortolotti Carla Cristina Sbardella Grasiela Martins James Marcel Silva Ribeiro Lamuniê Souza Liana Pamplona Maira Marina Martins Godinho Marcelo Pereira Marcos Alcides Medeiros Junior Maria Isabel Aragon Olavo Lajús Priscilla Geovana Pagani Silvana Henrique Silva Secretária Executiva Viviane Schalata Martins Tecnologia Osmar de Oliveira Braz Júnior (coordenador) Ricardo Alexandre Bianchini Rodrigo de Barcelos Martins Edição – Livro Didático Professor Conteudista Andréa Sabedra Bordin Marcelo Medeiro Andrik Dimitrii Braga de Albuquerque Design Instrucional Flavia Lumi Matuzawa Leandro Kingeski Pacheco Projeto Gráfico e Capa Equipe UnisulVirtual Diagramação Rafael Pessi Revisão Ortográfica B2B 7/12/2006 14:00:23 Sumário Apresentação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Palavras dos professores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Plano de estudo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE UNIDADE 1 – Introdução a GUI (Grafical User Interface) . . . . . . . . . . . . . . . . . .17 2 – Tratamento de Eventos em uma GUI . . . . . . . . . . . . . . . . . . . . . . .45 3 – Componentes de uma GUI (JCheckBox, JRadioButton, JComboBox e JList) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 4 5 6 7 8 9 10 11 12 13 14 15 – Trabalhando com Layout de Componentes . . . . . . . . . . . . . . .97 – Layout, JTabbedPane e componentes de Menu . . . . . . . . 121 – Modelando o Banco de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 – Conectando o Java ao Banco Dados . . . . . . . . . . . . . . . . . . . . . . 159 – Criando as Classes de Representação . . . . . . . . . . . . . . . . . . . . . 175 – Criando as Classes de Controle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 – Aplicação Exemplo: Controle de Projetos . . . . . . . . . . . . . . . . 205 – Introdução ao Desenvolvimento de Aplicações Web . . . 209 – Servlets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 – Java Server Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 – Java Standard Tag Library (JSTL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 – Aplicação Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Para concluir o estudo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sobre os professores conteudistas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Respostas e comentários das atividades de auto-avaliação . . . . . . . . . . . . . . . Linguagens de Programação II.indb 7 313 315 317 319 7/12/2006 14:00:24 Linguagens de Programação II.indb 8 7/12/2006 14:00:24 Palavras dos professores Olá, Você está iniciando a disciplina de Linguagem de Programação II. Para chegar até aqui você deve ter passado pelas disciplinas de Lógica de Programação I e II, Programação Orientada a Objetos, Banco de Dados I e II e Linguagens de Programação I. Isso quer dizer que você já tem plenas condições de assimilar o conteúdo de nível mais aprofundado que será abordado nesse livro. Esse livro abordará três tópicos muito importantes do mundo da programação: construção de GUI (Graphical User Interface), Acesso e manipulação de banco de dados e aplicação web. Primeiramente, serão apresentados para você os conhecimentos básicos sobre como construir uma GUI (Graphical User Interface). Uma interface gráfica de usuário é a tela ou “view” da aplicação que você desenvolve. O enfoque, nesse assunto, será sobre aplicações para desktop e utilizaremos para isso um conjunto de componentes da linguagem Java, denominados componentes Swing. Esse assunto será abordado ao longo de cinco unidades. O assunto das quatro unidades seguintes trata da conexão e manipulação de dados em um banco. Você aprenderá como construir uma aplicação em Java que faça conexão com um banco de dados e manipule (inserir, atualizar, deletar) dados nesse banco de dados. A décima unidade mostrará o desenvolvimento de uma aplicação exemplo completa, envolvendo a construção de uma GUI para entrada e saída dos dados e a manipulação desses dados em um banco de dados. As unidades finais apresentarão uma introdução ao desenvolvimento de uma aplicação web usando Java Servlets. Linguagens de Programação II.indb 9 7/12/2006 14:00:24 Universidade do Sul de Santa Catarina Como dito, todos os conteúdos abordados nesse livro têm um nível técnico um pouco mais elevado. Por isso, toda a atenção da sua parte é bem-vinda. Mas você certamente já sabe que essa atenção será recompensada à medida que você ver seus programas funcionando. Boa Sorte! Professores Andréa Sabedra Bordin, Marcelo Medeiros e Andrik Albuquerque 10 Linguagens de Programação II.indb 10 7/12/2006 14:00:24 Plano de estudo O plano de estudo visa orientá-lo/a no desenvolvimento do Projeto Integrador. Nele, você encontrará elementos que esclarecerão o contexto do mesmo e sugerirão formas de organizar o seu tempo de estudos. O processo de ensino e aprendizagem na UnisulVirtual leva em conta instrumentos que se articulam e se complementam. Assim, a construção de competências se dá sobre a articulação de metodologias e por meio das diversas formas de ação/ mediação. São elementos desse processo: o livro didático; o Espaço UnisulVirtual de Aprendizagem - EVA; as atividades de avaliação a distância (não serão feitas avaliações presenciais). Ementa Introdução a Java. Programação orientada a objetos. Programação Java: Multitarefa; Cliente/servidor; acesso a banco de dados; interface gráfica; APPLETS. JDBC. Deployment. Aplicações web com Java. Aplicações J2ME. Carga Horária A carga horária total da disciplina é 120 horas-aula, 8 créditos, incluindo o processo de avaliação. Linguagens de Programação II.indb 11 7/12/2006 14:00:24 Universidade do Sul de Santa Catarina Objetivos Geral: Fornecer ao aluno conhecimentos básicos sobre o desenvolvimento de interface gráfica de aplicação, assim como sobre a conexão de aplicação com banco de dados além do desenvolvimento de aplicações dinâmicas para web. Específicos: Conhecer os principais componentes Swing para o desenvolvimento de GUI. Aprender a manipular dados em um banco de dados via aplicação (software). Conhecer os fundamentos para o desenvolvimento de uma aplicação web de pequeno porte. Conteúdo programático/objetivos Os objetivos de cada unidade definem o conjunto de conhecimentos que você deverá deter para o desenvolvimento de habilidades e competências necessárias à sua formação. Neste sentido, veja, a seguir, as unidades que compõem o livro didático desta Disciplina, bem como os seus respectivos objetivos. Unidades de estudo: 15 Unidade 1 – Introdução a GUI (Grafical User Interface) Nesta unidade você terá uma visão geral dos componentes utilizados para a construção de GUI. Será mostrado o primeiro componente Swing JLabel e uma introdução ao conceito de interface. Unidade 2 – Tratamento de Eventos em uma GUI Nesta unidade você estudará, essencialmente, como funciona o tratamento de eventos em uma GUI. 12 Linguagens de Programação II.indb 12 7/12/2006 14:00:24 Linguagens de Programação I Unidade 3 – Componentes de uma GUI (JCheckBox, JRadioButton, JComboBox e JList) Nesta unidade você conhecerá outros componentes Swing. Unidade 4 – Trabalhando com Layout de Componentes Na unidade 4 você aprenderá a trabalhar com o layout dos componentes da tela, através do uso de outros gerenciadores de layout. Unidade 5 – Layout, JTabbedPane e componentes de Menu Nesta unidade você aprenderá uma pouco mais sobre layout, conhecerá outro componente Swing e aprenderá a construir GUI com menus. Unidade 6 – Modelando o Banco de Dados Na unidade 6 você relembrará como modelar um banco de dados e como criar o banco modelado em um SGBD. Unidade 7 – Conectando o Java ao Banco Dados Nesta unidade você aprenderá como conectar uma aplicação Java a um banco de dados, usando um driver JDBC. Unidade 8 – Criando as Classes de Representação Na unidade 8 você aprenderá a criar as classes de representação de dados, de um banco de dados. Unidade 9 – Criando as Classes de Controle Na unidade 9, você criará classes que permitam a execução de comandos SQL e a conexão e manipulação de dados em um banco de dados. 13 Linguagens de Programação II.indb 13 7/12/2006 14:00:25 Universidade do Sul de Santa Catarina Unidade 10 – Aplicação Exemplo: Controle de Projetos Nesta unidade será exibido o código completo de uma aplicação para Controle de Projetos, que envolverá a criação de GUI´s e a manipulação de dados no banco de dados. Unidade 11 – Introdução ao Desenvolvimento de Aplicações Web Nesta unidade serão apresentados o protocolo HTTP, aplicações CGI e os conceitos de desenvolvimento de aplicações web com a tecnologia Java. Unidade 12 – Servlets Nesta unidade você conhecerá o que são os Servlets e utilizará as funcionalidades oferecidas por essa tecnologia para verificar o desenvolvimento de uma aplicação web. Unidade 13 – Java Server Pages Na unidade 13 você conhecerá a tecnologia Java Server Pages e como ela facilita o desenvolvimento de aplicações web utilizando a tecnologia Java. Unidade 14 – Java Standard Tag Library (JSTL) Nesta unidade será apresentada a biblioteca JSTL, para facilitar ainda mais o desenvolvimento de aplicações web de uma forma padronizada. Unidade 15 – Aplicação Web Nesta unidade será apresentada uma aplicação completa dando continuidade ao projeto iniciado na unidade 10, porém, agora, com o foco no ambiente web. 14 Linguagens de Programação II.indb 14 7/12/2006 14:00:25 Linguagens de Programação I Agenda de atividades/ Cronograma Verifique com atenção o EVA, organize-se para acessar periodicamente o espaço da Disciplina. O sucesso nos seus estudos depende da priorização do tempo para a leitura; da realização de análises e sínteses do conteúdo; e da interação com os seus colegas e tutor. Não perca os prazos das atividades. Registre no espaço a seguir as datas, com base no cronograma da disciplina disponibilizado no EVA. Use o quadro para agendar e programar as atividades relativas ao desenvolvimento da Disciplina. 15 Linguagens de Programação II.indb 15 7/12/2006 14:00:25 Universidade do Sul de Santa Catarina Atividades Avaliação a Distância 1 Avaliação a Distância 2 Avaliação Presencial 1 Avaliação Presencial 2 (2ª chamada) Avaliação Final Demais atividades (registro pessoal) 16 Linguagens de Programação II.indb 16 7/12/2006 14:00:25 UNIDADE 1 Introdução a GUI (Grafical User Interface) 1 Objetivos de aprendizagem Entender o que é uma GUI e quais os seus principais componentes. Obter uma visão geral dos componentes Swing presentes numa GUI. Compreender o processo de criação de uma GUI com o componente JLabel. Entender o conceito de interface e suas principais aplicações. Seções de estudo Seção 1 Entendendo uma GUI (grafical user interface) Seção 2 Visão Geral dos Componentes Swing Seção 3 Criação da Primeira GUI - Componente JLabel Seção 4 Interface Linguagens de Programação II.indb 17 7/12/2006 14:00:25 Universidade do Sul de Santa Catarina Para início de conversa Nessa unidade, você será apresentado ao mundo da interface gráfica de usuário (GUI). Uma interface representa o “meio de campo” entre o usuário e a aplicação (software). É através da interface que o usuário pode se comunicar com o aplicativo, ou seja, inserir dados, visualizar informações, etc. Uma interface pode ser puramente textual ou gráfica. Interfaces gráficas já fazem parte do nosso dia-a-dia, desde o surgimento do sistema operacional Windows e, portanto, é necessário que você entenda os fundamentos básicos da sua construção. Seção 1 – Entendendo uma GUI (grafical user interface) Uma interface gráfica com o usuário GUI (grafical user interface) apresenta um mecanismo amigável para interagir com um aplicativo (é a tela do sistema). Uma GUI oferece ao aplicativo uma aparência e um comportamento. Observe o exemplo de GUI, a seguir, visualizada através da janela do navegador Internet Explorer com seus componentes GUI rotulados. Barra de título Barra de botões Barra de menus Botão Barra de rolagem FIGURA 1.1 – VISÃO DE UMA GUI 18 Linguagens de Programação II.indb 18 7/12/2006 14:00:25 Linguagens de Programação II Observe que as GUIs são construídas a partir de componentes GUI . Estes componentes podem ser chamados também de widget. Um componente GUI é um objeto com que o usuário interage na aplicação via mouse ou teclado ou outro tipo de entrada. A maioria dos aplicativos utiliza janelas (windows) ou caixas de diálogo para interagir com o usuário. Em geral, as caixas de diálogo são componentes GUI usadas para exibir mensagens importantes para o usuário ou para, em alguns casos, obter-se informações dele. Você sabe trabalhar com caixas de diálogo? Lembre-se que na disciplina de Programação Orientada a Objetos (POO), você utilizou somente este tipo de componente (as caixas de diálogo) para fazer interações com o usuário (entrada e saída de dados). Para exibir caixas de diálogo nos programas, use a classe JOptionPane que está no pacote javax.swing da API de Java (nesta disciplina, você explorará bastante as outras classes desse pacote). Lembre-se que a linguagem Java possui uma extensa biblioteca de classes prontas para os programadores usarem. Esta biblioteca é chamada de API (aplication programming interface). As classes nesta biblioteca são organizadas por funcionalidade, em estruturas chamadas pacotes (package). As classes dos componentes GUI estão nos pacotes javax.swing e java.awt. Consulte a documentação desses dois pacotes no seguinte site: http://java.sun.com/j2se/1.5.0/docs/api/ Unidade 1 Linguagens de Programação II.indb 19 19 7/12/2006 14:00:26 Universidade do Sul de Santa Catarina Até o momento, você muito provavelmente só utilizou essa classe (JOptionPane) do pacote Swing (será falado deste modo, daqui para a frente). E, muito provavelmente, somente os métodos static showInputDialog e showMessageDialog dessa classe foram utilizados. Porém, a classe JOptionPane oferece diversos tipos de caixas de diálogo e você pode customizar as existentes. Assim, por exemplo, você pode mudar o texto da barra de título, o tipo de ícone exibido, o nome dos botões, etc. Veja, agora, como customizar alguns dos métodos já conhecidos e apresentar outros métodos. showMessageDialog Esse método permite a você exibir uma caixa de diálogo com uma mensagem e um botão. Ele pode ser customizado, ou seja, você pode alterar o texto da barra de título e o ícone da mensagem. Para isso, você deve chamar esse método passando alguns argumentos adicionais. A forma abaixo é uma das maneiras de invocá-lo, embora existam outras que podem ser consultadas na documentação da API Java: showMessageDialog(Component parentComponent, Object message, String title, int messageType) Considere os seguintes parâmetros: parentComponent – determina o Frame (este conceito será aprendido logo) no qual a caixa de diálogo será mostrada; se for null, então o Frame default (padrão) é usado. message – mensagem a ser mostrada. title – texto mostrado na barra de título. messageType – determina o tipo de mensagem que aparecerá na caixa: ERROR_MESSAGE , INFORMATION_MESSAGE , WARNING_MESSAGE , QUESTION_MESSAGE ou PLAIN_MESSAGE (sem ícone). Um ícone diferencia o tipo de mensagem. 20 Linguagens de Programação II.indb 20 7/12/2006 14:00:26 Linguagens de Programação II De acordo com o tipo de mensagem (messageType) passado como argumento, os seguintes ícones podem aparecer na caixa de diálogo: question information warning error (cor amarela) (cor bordô) (cor vermelha) (cor verde) FIGURA 1.2 – ÍCONES POSSÍVEIS DE UMA CAIXA DE DIÁLOGO O código, abaixo, demonstra como customizar o texto da barra de título e o ícone dessa caixa de diálogo. Edite, compile e veja o resultado! import javax.swing.*; public class GuiCaixaDialogo{ public static void main(String arg[]){ //chamada do método passando somente os dois primeiros argumentos. Mostra a // mensagem e ícone default de informação JOptionPane.showMessageDialog(null,”Mensagem de Informação”); // chamada do método passando somente os quatro argumentos explicados acima //título customizado e ícone de informação JOptionPane.showMessageDialog(null,”Mensagem de Informação”,”Informação”, JOptionPane.INFORMATION_MESSAGE); Parâmetro que define o tipo da mensagem Parâmetro que muda o texto da barra de título //título customizado e ícone de perigo JOptionPane.showMessageDialog(null,”Mensagem de Perigo”,”Perigo”, JOptionPane. WARNING_MESSAGE); //título customizado e ícone de erro JOptionPane.showMessageDialog(null,”Mensagem de Erro”,”Erro”, JOptionPane. ERROR_MESSAGE); Unidade 1 Linguagens de Programação II.indb 21 21 7/12/2006 14:00:26 Universidade do Sul de Santa Catarina //título customizado e ícone de questão JOptionPane.showMessageDialog(null,”Mensagem de Questionamento”,”Questionamento”, JOptionPane.QUESTION_MESSAGE); //título customizado e sem ícone JOptionPane.showMessageDialog(null,”Mensagem simples”,”Simples”, JOptionPane.PLAIN_ MESSAGE); } } //fim da classe Atenção! Em geral, a barra de título de uma janela adota o estilo que emprega o uso de letra inicial maiúscula em cada palavra significativa do texto e não termina com pontuação. Veja algumas outras caixas de diálogo: showOptionDialog Com este método, você pode mostrar uma caixa com botões específicos, ícone, mensagem e título. Você pode mudar o texto que aparece nos botões do diálogo e realizar outros tipos de customização. Veja os parâmetros necessários para usar esse método: showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) Acompanhe os parâmetros: parentComponent – determina o Frame (você aprenderá isto logo) no qual a caixa de diálogo será mostrada; se for null, então o Frame default (padrão) é usado. 22 Linguagens de Programação II.indb 22 7/12/2006 14:00:27 Linguagens de Programação II message – mensagem a ser mostrada. title – mensagem de texto mostrada na barra de título. optionType – tipo de opções de botão que aparecerão: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION OK_CANCEL_ OPTION. messageType – determina o tipo de mensagem que aparecerá na caixa: ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_ MESSAGE, QUESTION_MESSAGE, ou PLAIN_ MESSAGE. icon – ícone mostrado na caixa. options – um array de objetos indicando as possíveis escolhas que o usuário pode fazer, normalmente um array de String com os nomes dos botões. initialValue – opção default de botão que aparecerá na caixa. Deve ser usado somente se a opção options também for usada. Pode ser null. Retorno do método: Um valor inteiro indicando a opção escolhida pelo usuário, ou CLOSED_OPTION se o usuário fechou a janela. O código abaixo exemplifica a utilização desse método: import javax.swing.*; public class GuiCaixaDialogoOptionDialog{ public static void main(String arg[]){ //array de 3 posições, onde cada uma contém o texto de um botão. String[] options = {“Sim, por favor, “Não, obrigada”, “Cancela”}; //compare os parâmetros do método showOptionDialog com a explicação dos parâmetros acima //parâmetro options é o array declarado anteriormente. Contém o nome dos botões //parâmetro options[0] indica que o primeiro botão estará selecionado //variável n armazenará o número do botão que o usuário clicou int n = JOptionPane.showOptionDialog(null,”Confirma o pedido?”, Unidade 1 Linguagens de Programação II.indb 23 23 7/12/2006 14:00:27 Universidade do Sul de Santa Catarina “Confirmação do Pedido”, JOptionPane.YES_NO_CANCEL_OPTION, //optionType JOptionPane.QUESTION_MESSAGE, //messageType null, //sem icon options, options[0]); // n pode ser testado em relação aos valores inteiros literais 0, 1 ou 2 (ordem dos botões) ou em relação //aos atributos static final da classe JOptionPane: YES_OPTION, NO_OPTION E CANCEL_OPTION. if ((n = = 0) || (n = = JOptionPane.YES_OPTION )) JOptionPane.showMessageDialog(null,”Pedido confirmado”); else if (n= =1) JOptionPane.showMessageDialog(null,”Pedido negado”); else if (n = = 2) JOptionPane.showMessageDialog(null,”Pedido cancelado”); else if (n = = JOptionPane.CLOSED_OPTION) JOptionPane.showMessageDialog(null,”Janela fechada”); System.exit(0); // o atributo JOptionPane.CLOSED_OPTION indica que a janela foi fechada. } } showInputDialog Lembre-se que você já conhece esse método. Ele permite uma entrada de dados por parte do usuário e algumas customizações. A novidade, mostrada aqui, é que o usuário pode escolher, ao invés de digitar, um entre vários valores estabelecidos previamente. Esse método possui algumas variações, ou seja, ele pode ser chamado passando-se um conjunto reduzido de argumentos (como foi feito em POO) ou passando-se vários argumentos, o que possibilita uma customização maior. Abaixo é apresentada a forma mais completa de chamar esse método: showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) 24 Linguagens de Programação II.indb 24 7/12/2006 14:00:27 Linguagens de Programação II Veja o significado dos Parâmetros (só os parâmetros novos são explicados, pois, para os outros parâmetros, aplica-se a mesma explicação do método mostrado anteriormente): icon – imagem do tipo Icon pode ser mostrada. selectionValues – array de objetos com vários valores possíveis de serem escolhidos pelo usuário. Normalmente um array de String. initialSelectionValue – valor usado para inicializar o campo de entrada. É o valor que aparece no topo do campo. Retorno do método: Entrada ou escolha do usuário ou null se o usuário cancelar a entrada. O código abaixo exemplifica a utilização desse método: import javax.swing.*; public class GuiCaixaDialogoInputDialog{ public static void main(String arg[]){ //array com as opções de escolha String[] possibilidades = {“feminino”, “masculino”}; //nessa chamada de método é necessário fazer o cast (conversão) para String pois o dado retornado é do tipo Object String s = (String)JOptionPane.showInputDialog(null,”Escolha a opção:”, “Caixa de Entrada Customizada”, JOptionPane.PLAIN_MESSAGE, null, possibilidades, possibilidades[0]); if (s.equals(“feminino”)) JOptionPane.showMessageDialog(null,”Feminino”); else JOptionPane.showMessageDialog(null,”Masculino”); System.exit(0); } } Unidade 1 Linguagens de Programação II.indb 25 25 7/12/2006 14:00:27 Universidade do Sul de Santa Catarina Existem outros métodos e variações desses métodos além dos mostrados aqui na classe JOptionPane. Para maiores informações, consulte a documentação da API Java: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JOptionPane.html Caro aluno, a idéia, aqui, foi introduzir para você as imensas possibilidades de uso de apenas uma das classes do pacote de componentes GUI, chamado Swing. Seção 2 - Visão Geral dos Componentes Swing Embora seja possível você realizar a entrada e a saída de dados utilizando as caixas de diálogo JOptionPane, a maioria dos aplicativos GUI exigem interfaces com usuários, mais elaboradas e personalizadas, com uma série de componentes sendo exibidos em uma janela. Neste sentido, conheça outros tipos de componentes GUI. A tabela, abaixo, mostra alguns dos componentes GUI mais utilizados nas aplicações: Componente Descrição JLabel Exibe texto não editável ou ícones. JTextField Permite ao usuário inserir dados através do teclado. Pode exibir texto editável ou não editável. JButton Botão. JCheckBox JRadioButton JComboBox JList JPanel Opção associada a um texto que pode ou não ser selecionada. Podem-se selecionar várias opções de checkbox. Opção associada a um texto que pode ou não ser selecionada. Seleciona-se uma entre várias opções de radio. Fornece uma lista de itens a partir da qual o usuário pode escolher um deles ou digitar um valor na própria caixa. Fornece uma lista de itens a partir da qual o usuário pode escolher um ou vários itens. Fornece uma área (painel, container) onde outros componentes podem ser colocados e organizados. 26 Linguagens de Programação II.indb 26 7/12/2006 14:00:28 Linguagens de Programação II Observe, a seguir, a interface de uma aplicação com todos os componentes listados acima: J Label J Textfield JButton J ComboBox J List JRadioButton JCheckBox JFrame FIGURA 1.3 – GUI COM VÁRIOS COMPONENTES Swing e AWT Para construir as aplicações GUI, você deve utilizar dois conjuntos de componentes GUI no Java: Swing. AWT. Antes do Swing ser construído no J2SE 1.2, as GUI de aplicações em Java eram construídas com componentes do Abstract Window Toolkit (AWT), que estão no pacote java.awt. Quando uma aplicação GUI em Java é construída com componentes AWT e é executada em diferentes plataformas, esses componentes são exibidos diferentemente em cada uma dessas plataformas. Além disso, às vezes, a maneira como um usuário interage com um componente AWT difere entre as plataformas. Por exemplo, uma aplicação que contém um botão (objeto Button do pacote java.awt), ao ser executada no sistema operacional Windows, terá a mesma aparência dos botões do sistema Unidade 1 Linguagens de Programação II.indb 27 27 7/12/2006 14:00:28 Universidade do Sul de Santa Catarina operacional Windows. Se a aplicação for executada no sistema operacional do Macintosh, então esta aplicação terá a mesma aparência dos botões desse sistema. Saiba Mais! A aparência e comportamento do sistema em determinada plataforma são conhecidos como look and feel. Os componentes Swing (pacote javax.swing) permitem especificar uniformemente a aparência e comportamento de um aplicativo em todas plataformas ou utilizar a aparência e o comportamento personalizados de cada plataforma. Atenção! Os componentes Swing são implementados em Java. Deste modo, tais componentes são mais portáveis e flexíveis do que os componentes do pacote AWT. Estes últimos são baseados nos componentes GUI da plataforma onde a aplicação é executada. Ou seja, os componentes AWT operam tendo por base as funcionalidades de alguma biblioteca gráfica do sistema onde a aplicação é executada. Componentes GUI leves e pesados Os componentes GUI são classificados como leves e pesados. Os componentes leves não são vinculados à plataforma local. A maioria dos componentes Swing são componentes leves. Os componentes de peso são vinculados à plataforma local porque contam com o sistema de janela desta plataforma para determinar sua funcionalidade, aparência e comportamento. Os componentes AWT são componentes pesados. Alguns poucos componentes do pacote Swing também são. 28 Linguagens de Programação II.indb 28 7/12/2006 14:00:28 Linguagens de Programação II Seção 3 - Criação da Primeira GUI - Componente JLabel Criar uma GUI mais elaborada envolve, primeiramente, a criação de um container, que é, por sua vez, um componente que pode receber outros componentes. Em uma aplicação GUI desktop, normalmente o container usado é um frame (uma janela com barra de título, botões de minimizar, maximizar e fechar a janela). Uma janela ou frame é uma instância da classe JFrame ou uma subclasse de JFrame. Tal classe fornece os atributos e comportamentos básicos de uma janela. Nesse container (janela ou frame) podem ser adicionados vários outros componentes GUI. Na figura anterior, 1.3, você tem uma idéia dos componentes mais usados nas aplicações. Bom, comece criando uma aplicação GUI com uma janela e vários componentes que têm como função rotular, ou seja, especificar a função de outros componentes na janela. Esse componente é criado com a classe JLabel. JLabel exibe uma linha de texto, uma imagem ou tanto texto como imagem. Para maiores informações sobre a classe JLabel, consulte a documentação da API: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JLabel.html A aplicação GUI está dividida em duas classes: A classe GuiJLabel.java cria a janela com os componentes JLabel inseridos nela. A classe TesteJLabel.java possui o método main que cria uma instância (objeto) da classe GuiJLabel. Unidade 1 Linguagens de Programação II.indb 29 29 7/12/2006 14:00:28 Universidade do Sul de Santa Catarina O código, abaixo, demonstra utilização do componente JLabel: 0 //Classe GuiJLabel.java 1 2 3 4 5 6 //classe gerenciadora de layout que especifica como os componentes são organizados import java.awt.FlowLayout; import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JLabel; //classe do componente de rótulo (label). Pode exibir texto e imagem import javax.swing.SwingConstants; //classe de constantes usadas pelos componentes Swing import javax.swing.Icon; //interface utilizada para manipular imagens import javax.swing.ImageIcon; /classe utilizada para carregar imagens 7 public class GuiJLabel extends JFrame{ 8 9 10 private JLabel label1; private JLabel label2; private JLabel label3; 11 public GuiJLabel(){ 12 super(“Exemplo JLabel”); 13 setLayout(new FlowLayout()); 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 } label1 = new JLabel(“Tecnólogo em Web Design e Programação”); label1.setToolTipText(“Este é o rotulo 1”); add(label1); Icon bug = new ImageIcon(“metal-Error.gif”); //esta imagem pode ser substituída por outra label2 = new JLabel(“Rótulo com texto e imagem”, bug,SwingConstants.LEFT); label2.setToolTipText(“Este é o rótulo 2”); add(label2); label3 = new JLabel(); label3.setText(“Rótulo com imagem e texto embaixo”); label3.setIcon(bug); label3.setHorizontalTextPosition(SwingConstants.CENTER); label3.setVerticalTextPosition(SwingConstants.BOTTOM); label3.setToolTipText(“Este é o rótulo 3”); add(label3); 29 } Agora, acompanhe a análise linha a linha do código da classe anterior: Linha 7 – observe que a classe GuiJLabel estende a classe JFrame, ou seja, é uma subclasse de JFrame. Logo ela herdará a aparência e comportamento de uma janela típica. Dentro desta janela serão adicionados outros componentes, neste caso, alguns componentes JLabel e imagens (Icon). 30 Linguagens de Programação II.indb 30 7/12/2006 14:00:28 Linguagens de Programação II Linhas 8 a 10 – veja que são criados três atributos do tipo JLabel chamados label1, label2 e label3, que serão os componentes adicionados à janela. Só foram criadas as referências para os componentes. Eles só serão instanciados no construtor dessa classe (lembre-se que todo componente é um objeto). Linha 11 – método construtor da classe (lembre-se que todo o construtor tem o mesmo nome da classe e não tem tipo de retorno). Normalmente, é no construtor que você constrói a GUI que é exibida na tela, ou seja, é nele que é chamado o construtor da sua superclasse JFrame (esse constrói a janela), instancia (cria) os componentes (objetos), os configura e os adiciona à janela ou frame (se GuiJLabel estende JFrame, então ela é um JFrame ou abreviando, um frame). Linha 12 – chamada ao método construtor da superclasse JFrame (chama-se o construtor de uma superclasse com a palavra super, está lembrado?). Na chamada do construtor da super foi passado o argumento do tipo String “Exemplo JLabel”. Assim, este texto será exibido na barra de título da janela. Linha 13 – aqui é chamado o método setLayout e passado uma referência (new) do tipo de layout desejado, nesse caso FlowLayout. Ao construir uma GUI, os componentes devem ser adicionados a um container, nesse caso, à janela criada com JFrame. Geralmente é preciso decidir em qual posição esses componentes serão adicionados e isso pode ser feito através de um gerenciador de layout. Existem algumas classes gerenciadoras de layout que se pode utilizar, mas você verá isto mais tarde. A princípio, você utilizará o gerenciador de layout chamado FlowLayout. Embora existam IDE´s (ambiente de desenvolvimento integrado) que possuem ferramentas gráficas que ajudam a fazer o desenho de uma interface (ou seja, com um simples clicar e arrastar você coloca e posiciona os componentes na janela), você não utilizará este recurso neste livro. Tal procedimento tem o intuito de fazer com que você aprenda mais sobre os componentes GUI, suas configurações e como posicioná-los na janela através dos gerenciadores de layout. Ou seja, você aprenderá a construir aplicações GUI “na mão”. Unidade 1 Linguagens de Programação II.indb 31 31 7/12/2006 14:00:29 Universidade do Sul de Santa Catarina Ao usar o gerenciador de layout FlowLayout, os componentes são colocados no container (janela) da esquerda para a direita, na ordem em que são anexados ao container no programa. Quando não houver mais espaço para os componentes na mesma linha, eles são colocados na próxima linha, também da esquerda para a direita. Se o container for redimensionado, então o gerenciador FlowLayout ajustará os componentes novamente. Linha 14 – depois que especificar o layout, você pode criar os componentes, configurá-los e adicioná-los ao container. Veja que, nessa linha é criado o primeiro componente (objeto) JLabel e armazenado sua referência na variável label1. Ao chamar o construtor dessa classe é passado o argumento String “Tecnólogo em Web Design e Programação”, e isto fará com que esse texto seja exibido na janela. Linha 15 – o método setToolTipText é aqui chamado precedido da referência ao componente JLabel recém criado. É passada como argumento uma String (mensagem de texto) que aparecerá quando o usuário posicionar o mouse em cima desse componente. Linha 16 – o método add adiciona o componente recém criado ao container GuiJLabel. Esse método é herdado da superclasse JFrame (na realidade o método é herdado indiretamente da classe Container) e é passado a ele a referência (label1) do componente JLabel. Atenção! Lembre-se que os componentes sempre devem ser adicionados a um container. Esse assunto faz parte dos conhecimentos de Orientação a Objetos. Ele é muito importante para o entendimento de vários conceitos relacionados ao uso de componentes GUI e, por isto, será dedicada uma seção especial a este assunto no final desta unidade. Linha 17 – Os ícones são normalmente utilizados para identificar as funcionalidades de um sistema. Vários componentes Swing podem exibir imagens. Primeiramente, você precisa criar um objeto do tipo Icon e associar uma imagem (.gif, .png, .jpg) a ele. Depois você passa esse objeto para o construtor ou método do componente Swing. Assim foi feito nas linhas 17 e 18. Na linha 17, foi criado um objeto do tipo ImageIcon, (pacote javax.swing) que é uma classe que implementa a interface Icon, passando-se como argumento o nome e a extensão da imagem. 32 Linguagens de Programação II.indb 32 7/12/2006 14:00:29 Linguagens de Programação II A imagem deve estar na mesma pasta dos arquivos fonte. A referência desse objeto é armazenada na variável do tipo Icon. Na linha 18, foi criado o componente JLabel label2 e passados, como argumentos para o seu construtor, o texto a ser exibido, o objeto Icon criado e uma constante que representa o alinhamento do texto no componente JLabel, nesse caso à esquerda. Atenção! A interface SwingContants - que pode ser acessada no endereço http://java.sun.com/j2se/1.5.0/docs/ api/javax/swing/SwingConstants.html - possui um conjunto de atributos que fazem a configuração de posicionamento da tela de vários componentes Swing. Veja que é com essas linhas que um JLabel pode exibir uma imagem (objeto Icon). Linha 19 e 20 – especifica-se aqui o texto de dica do label2 e adiciona-se ele ao container. Linha 21 – cria-se, aqui, um novo componente JLabel e armazena-se a referência ao label3. Note que o construtor de JLabel está sem argumentos. Qual texto será exibido neste label (rótulo)? O texto e imagem serão configurados logo abaixo, com métodos específicos. Existem vários outros métodos na classe JLabel que podem ser usados para configurar o componente. Linha 22 – configura o texto a ser exibido no label através do método setText(); Linha 23 – configura a imagem a ser exibida junto com o texto através do método setIcon(). É passado como argumento o objeto do tipo Icon, chamado bug, declarado anteriormente. Linha 24 – configuração da posição horizontal do texto no label através do método setHorizontalTextPosition(). É passado como argumento a constante SwingConstants.CENTER. Isto faz com que o texto seja posicionado no centro do label em relação ao alinhamento horizontal. Unidade 1 Linguagens de Programação II.indb 33 33 7/12/2006 14:00:29 Universidade do Sul de Santa Catarina Linha 25 – configuração da posição vertical do texto no label através do método setVerticalTextPosition (). É passado como argumento a constante SwingConstants.BOTTOM. Isto faz com que o texto seja posicionado embaixo, dentro do label em relação ao alinhamento vertical. Linha 26 e 27 – especifica o texto de dica do label3 e o adiciona ao container. A seguir está o código da classe TesteJLabel.java. Essa classe é responsável por criar uma instância (objeto) do tipo GuiJLabel, configurar a operação de fechamento da janela, definir seu tamanho e torná-la visível. 0 1 2 3 4 5 6 7 8 import javax.swing.JFrame; public class TesteJLabel{ public static void main(String arg[]){ GuiJLabel guijlabel = new GuiJLabel(); guijlabel.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guijlabel.setSize(275,280); guijlabel.setVisible(true); } } Veja a análise do código anterior linha a linha: Linha 0 – importa-se a classe JFrame, pois na linha 4 se usa uma constante dessa classe. Linha 3 – criação do objeto do tipo GuiJLabel, ou seja, criação da janela. Lembre-se que é no construtor de GuiJLabel que a janela é criada e que se adicionam os componentes a ela. Linha 4 – por padrão, fechar uma janela a faz ficar oculta. Neste caso, ao fechar a janela guijlabel você quer terminar o aplicativo. O método que faz essa configuração é setDefaultCloseOperation (). Deve ser passado o argumento constante JFrame.EXIT_ON_ CLOSE. É ela que indica que o programa deve ser terminado quando a janela fechar. 34 Linguagens de Programação II.indb 34 7/12/2006 14:00:29 Linguagens de Programação II Linha 5 – o método setSize () especifica a largura e altura da janela. Linha 6 – o método setVisible(), com o argumento true, permite exibir a janela na tela. Agora que você analisou o código dessas duas classes, edite, compile e teste a sua primeira aplicação GUI. Não esqueça de olhar a documentação do componente JLabel para explorar seus outros recursos. A figura, a seguir, ilustra a aparência dessa aplicação. FIGURA 1.4 – GUI DA APLICAÇÃO TESTEJLABEL Seção 4 - Interface Como escrito anteriormente, o entendimento do conceito de interface é importante, e será estudado antes de você ver outros conceitos e componentes GUI. Uma interface é uma espécie de classe ou estrutura que inicia com a palavra-chave interface ou public interface e possui somente métodos que são implicitamente public abstract e/ou atributos que são public static final. Unidade 1 Linguagens de Programação II.indb 35 35 7/12/2006 14:00:30 Universidade do Sul de Santa Catarina Você lembra que no livro de POO foi visto uma série de modificadores (palavras usadas na definição de uma classe, atributo ou método)? Revise rapidamente. Sugestão! Revise todos os capítulos que abordam orientação a objetos do livro de POO. Alguns destes modificadores são chamados de modificadores de acesso (public, private, protected), pois sua função é determinar como (de que lugar) uma classe, método ou atributo pode ser acessado. Outros são chamados modificadores gerais e nessa categoria estão: static – um método com o modificador static pode ser chamado precedido apenas do nome da classe, sem que nenhum objeto daquela classe tenha sido criado; o atributo static faz com o que o atributo seja compartilhado por todos os objetos criados a partir da classe onde ele foi definido. Ou seja, o atributo é da classe e não de cada objeto. final – um método com o modificador final não pode ser redefinido, sobrescrito em uma subclasse; o atributo final é chamado de constante porque o seu valor nunca muda, é sempre fi xo. O atributo final deve ser inicializado com um valor no momento da sua definição ou no método construtor da classe. abstract – uma classe abstract não pode ter objetos criados (instanciados) a partir dela; o método abstract não tem implementação, é um método vazio, sem código. Pode ser usado num contexto de herança, numa superclasse, quando a lógica do método é diferente para cada subclasse desta superclasse. Todo o método abstract deve ser obrigatoriamente redefinido (sobrescrito) por todas as subclasses da superclasse onde o método abstract está. 36 Linguagens de Programação II.indb 36 7/12/2006 14:00:30 Linguagens de Programação II Portanto, depois dessa breve revisão, deve ter ficado mais claro o que são atributos static final (com valor fi xo) e métodos abstract (sem implementação). Somente estes itens são colocados numa interface. Para quê serve e como é utilizada uma interface? A interface é diferente de uma classe porque não se podem criar objetos a partir de uma interface. A interface é utilizada (implementada) por uma classe. Pode ser utilizada nas seguintes situações (1 e 2): 1) Java não suporta herança múltipla, ou seja, uma classe (subclasse) não pode herdar ou estender mais que uma classe (superclasse). Uma alternativa para essa restrição são as interfaces, pois uma classe pode implementar (implements) várias interfaces. Como todos os métodos de uma interface são abstract, eles devem ser obrigatoriamente redefinidos nas classes que implementam esta interface. Uma classe pode implementar (uma espécie de herança) várias interfaces, resolvendo, portanto, a restrição de herança múltipla apresentada anteriormente. A indicação que uma classe implementa outra classe se dá pela palavra-chave implements. Veja o exemplo: public class Quadrilatero implements CalculoFiguras,.....,.... { } Observe que CalculoFiguras é uma interface e que Quadrilátero é uma classe que implementa CalculoFiguras e mais outras interfaces, se houver necessidade. Unidade 1 Linguagens de Programação II.indb 37 37 7/12/2006 14:00:30 Universidade do Sul de Santa Catarina Já que Quadrilátero implementa CalculoFiguras, ela tem que redefinir, obrigatoriamente, todos os métodos abstract de CalculoFiguras. Se isto não for feito, Quadrilátero se torna uma classe abstract e uma mensagem de erro aparece após a compilação, indicando que ela deve ser declarada como abstract. Lembre-se! Uma classe abstract é aquela que não pode ter objetos instanciados. Uma interface é utilizada quando existe um comportamento ou operação (método) padrão, cuja lógica é específica para cada classe e que deve ser executado por classes que não estão relacionadas somente através de Herança. Acompanhe o exemplo: O comportamento ou método calculaArea() deve ser executado pelos objetos das classes da hierarquia Quadrilátero (superclasse), Trapézio e Retângulo (subclasses) - (estas três classes estão relacionadas através de herança) - e, também, pelos objetos da classe Triângulo que não faz parte desse relacionamento. Note que a lógica para calcular a área dessas figuras é diferente para cada uma. A primeira solução seria implementar um método abstract (sem lógica) na superclasse Quadrilátero e redefini-lo com a lógica apropriada nas subclasses Trapézio e Retângulo. Porém, se esse método ou comportamento for colocado somente na superclasse Quadrilátero, então só será visto e redefinido pelas subclasses Trapézio e Retângulo. A classe Triângulo não enxerga esse método, pois não faz parte da hierarquia de herança. O que fazer, então? Uma solução é criar uma interface e inserir esse comportamento (método) calculaArea() lá. Você pode criar uma interface chamada CalculoFiguras e inserir o método calculaArea(). Lembre-se que métodos numa interface são sempre abstract (sem implementação). Assim, todas as classes (Trapézio, Retângulo e Triângulo) poderão implementar 38 Linguagens de Programação II.indb 38 7/12/2006 14:00:30 Linguagens de Programação II essa interface. Isto quer dizer que terão que, obrigatoriamente, redefinir o(s) método(s) abstract definidos nessa interface. O código, abaixo, demonstra a implementação dessa interface. Esse código deve ser salvo num arquivo chamado CalculoFiguras.java. Depois de editar, o código deve ser somente compilado. public interface CalculoFiguras{ public abstract double calculaArea(); //os modicadores public abstract não são obrigatórios } Agora, várias classes podem implementar essa interface. Seguindo o exemplo, as classes que devem enxergar e redefinir o método calculaArea() são Trapézio, Retângulo e Triângulo. Como Trapézio e Retângulo são subclasses de Quadrilatero, é esta superclasse que deve implementar a interface CalculoFiguras. Triangulo também deve implementar a interface CalculoFiguras. Cada classe deve ser editada e compilada em um arquivo.java separado. Não é necessário que você implemente esse código. A intenção é apenas demonstrar a utilização de uma interface. //superclasse Quadrilátero implementa a interface CalculoFiguras public class Quadrilatero implements CalculoFiguras { //atributos e métodos .. } //subclasse Trapézio estende a classe Quadrilátero public class Trapezio extends Quadrilatero{ //atributos e métodos .. public double calculaArea(){ //... } } //subclasse Retângulo estende a classe Quadrilátero public class Retangulo extends Quadrilatero{ //atributos e métodos .. public double calculaArea(){ //... } } Unidade 1 Linguagens de Programação II.indb 39 39 7/12/2006 14:00:30 Universidade do Sul de Santa Catarina Note que somente a superclasse implementa a interface. Com este procedimento, o método calculaArea() deveria ser, obrigatoriamente, redefinido nesta superclasse. Caso não seja redefinido nesta superclasse, como será o caso (porque não existe cálculo de área a ser implementado na superclasse Quadrilatero), então a superclasse Quadrilátero deve se tornar abstract e este método, por sua vez, é repassado através da herança para todas as subclasses, devendo ser obrigatoriamente redefinido em todas elas. É exatamente nas subclasses que deve ser implementado o cálculo da área, já que ele é diferente para Trapezio e para Retangulo. A classe Triângulo não pertence à hierarquia de herança das classes acima, mas ela também possui o comportamento ou método específico para calcular a área. Ela deve implementar a interface CalculoFiguras e, assim, tem que redefinir, obrigatoriamente, o método abstract dessa interface. Confira no código seguinte: //Classe Triangulo implementa a interface CalculoFiguras public class Triangulo implements CalculoFiguras { //atributos e métodos .. public double calculaArea(){ //... } } Em resumo, a interface é utilizada quando classes díspares (não relacionadas) precisam compartilhar métodos e atributos em comum. Assim, permite-se que os métodos de objetos (classes) que implementam uma interface sejam processados polimorficamente (uso de polimorfismo). 40 Linguagens de Programação II.indb 40 7/12/2006 14:00:31 Linguagens de Programação II Atenção! Polimorfismo é um conceito que você estudou em POO, mas não será abordado neste livro porque ele não é necessário para construir aplicações GUI. Final do exemplo 2) Outra aplicação de interface refere-se à possibilidade de utilizá-la como um repositório de constantes. Ou seja, você pode declarar numa interface um conjunto de constantes (valores fi xos) que podem ser usados por várias classes. Atenção! Lembre-se que todo atributo numa interface é static e final. Observe o código abaixo: public interface Constantes{ //esta interface deve ser salva no arquivo Constantes.java int UM = 1; int DOIS = 2; int TRES = 3; } public class TesteInterface{ //note que esta classe não precisa implementar a interface Constantes public static void main(String args[]){ if (Constantes.UM = = 1) //nome da interface.nome do atributo System.out.println(“é igual a 1”); } } Unidade 1 Linguagens de Programação II.indb 41 41 7/12/2006 14:00:31 Universidade do Sul de Santa Catarina Síntese Nessa unidade, você conheceu o conceito de GUI. Portanto, já sabe que uma GUI é composta por vários outros componentes, também conhecidos como widgets. A maioria dos componentes usados para construir uma GUI são componentes leves do pacote javax.swing. Você também construiu sua primeira GUI. Foi uma GUI simples, somente com componentes do tipo rótulo ou JLabel, mas isto já permitiu que você tenha uma noção de como uma GUI pode ser construída. No final da unidade, você ainda estudou um conceito muito importante da orientação a objetos, o conceito de interface. Interfaces são muito utilizadas na construção de GUIs, embora na GUI construída nesta unidade ela não tenha sido utilizada. É importante que esses conceitos sejam bem assimilados. Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Escolha alguma aplicação com interface gráfica, faça um print screen dela e identifique os componentes GUI inseridos nela, mais especificamente a classe em Java responsável pela criação desse componente. Alguns componentes podem ser novos para você. 2) Complete o primeiro exemplo de código que está incompleto na seção 4 – Interface. Crie a interface, as três classes (superclasse e as duas subclasses) e outra classe com o método main() para testar essa aplicação. 42 Linguagens de Programação II.indb 42 7/12/2006 14:00:31 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando a seguinte referência, principalmente os capítulos 10, 11 e 22: DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. Também consulte: SILVA, Ivan José de Mecenas. Java 2: fundamentos Swing e JDBC. Rio de Janeiro: Editora Alta Books, 2003. Consulte, também, os seguintes sites: http://java.sun.com/docs/books/tutorial/uiswing/index.html (Creating a GUI with JFC/Swing) Unidade 1 Linguagens de Programação II.indb 43 43 7/12/2006 14:00:31 Linguagens de Programação II.indb 44 7/12/2006 14:00:31 UNIDADE 2 Tratamento de Eventos em uma GUI 2 Objetivos de aprendizagem Entender o processo de tratamento de eventos em uma GUI. Utilizar os componentes JTextField e JButton em uma GUI. Conhecer os principais tipos de eventos e suas interfaces. Seções de estudo Seção 1 Introdução ao Tratamento de Eventos Seção 2 Componente JTextField e JButton Seção 3 Tipos de Eventos GUI e suas Interfaces Seção 4 Entendendo o Tratamento de Eventos Linguagens de Programação II.indb 45 7/12/2006 14:00:31 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você aprenderá o processo de tratamento de eventos de um GUI. Ele é importante porque a maioria dos processamentos que você deseja programar na sua aplicação é acionado através da interação do usuário com algum componente presente na GUI. Quando essa interação acontece, eventos são gerados e devem ser tratados adequadamente para que o processamento seja executado corretamente. Esse processo será apresentado em ordem de dificuldade crescente durante as seções desta unidade. É importante que você leia e releia esta unidade, pois dependerá dela o entendimento das unidades seguintes. Nesta unidade, também serão apresentados dois componentes novos: JTextField (campo de texto) e JButton (botão). Seção 1 – Introdução ao Tratamento de Eventos Ao interagir com os componentes GUI de uma aplicação, o usuário indica a tarefa que deve ser executada pela aplicação. Por exemplo, em uma aplicação qualquer, ao clicar num botão com um rótulo Soma, provavelmente, a tarefa de somar alguns números será executada. Num editor de texto como o Word, o ato de clicar no botão com o ícone de um disquete (botão Salvar) indica que a tarefa de salvar o documento será executada. Para que você consiga programar uma tarefa em uma aplicação GUI é necessário entender como funciona o tratamento de eventos. Quando o usuário interage com um componente GUI, um evento é disparado (um evento também é um objeto – aliás, tudo é objeto em uma linguagem orientada a objeto). 46 Linguagens de Programação II.indb 46 7/12/2006 14:00:31 Linguagens de Programação II Por exemplo, o clique do mouse num botão dispara um evento; digitar caracteres num campo de texto dispara um evento; passar o mouse por cima de algum componente na tela dispara um evento; selecionar um item numa caixa de seleção (combobox) dispara um evento; fechar a janela dispara um evento, etc. Assim, observa-se que a maioria das ações do usuário numa GUI dispara eventos. Um evento precisa ser “tratado”, ou seja, a tarefa que você quer programar deve ser colocada dentro de uma estrutura que sempre é executada quando o evento é disparado. Voltando ao primeiro exemplo, ao clicar no botão Soma um evento será disparado e as linhas de código associadas a esse evento serão executadas (caso sejam programadas). Nessas linhas de código estará a programação da soma que você quer que aconteça, por exemplo, a soma de, no mínimo, dois números. Por enquanto, você fica com essa breve explicação. Logo mais, verá que é necessário que qualquer componente esteja “atento” ou “ouvindo” esses eventos... A seguir, você estuda dois novos componentes JTextField e JButton, além de uma aplicação onde o tratamento de eventos ficará mais claro para você. Seção 2 – Componente JTextField e JButton A classe JTextField (que faz parte do pacote javax.swing) representa o componente conhecido como campo de texto, onde o usuário pode inserir texto numa única linha através do teclado. O texto também pode ser exibido nesse componente sem que o usuário entre com ele. Para digitar o texto nesse componente é necessário que o foco esteja nele. Um componente recebe o foco quando você clica nele. Unidade 2 Linguagens de Programação II.indb 47 47 7/12/2006 14:00:32 Universidade do Sul de Santa Catarina Consulte a documentação dessa classe em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JTextField.html A classe JButton (que faz parte do pacote javax.swing) representa o componente botão, que é utilizado nas aplicações GUI para executar uma ação específica (ao ser clicado), como somar, salvar dados de um formulário, deletar dados, etc. Um botão pode exibir texto e imagem (objeto Icon) dentro dele. O texto é chamado de rótulo do botão. Consulte a documentação dessa classe em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JButton.html A aplicação GUI, a seguir, demonstra o uso desses dois componentes numa interface onde o usuário deve entrar com dois números (nos componentes JTextField) e clicar no botão Soma (JButton). Após o clique, será exibida a soma dos dois números em outro componente JTextField. A figura 2.1 demonstra tal aplicação, após ser executada: FIGURA 2.1 – GUI DA APLICAÇÃO TESTEJTEXTFIELD 48 Linguagens de Programação II.indb 48 7/12/2006 14:00:32 Linguagens de Programação II Veja o código da classe GuiJTextField.java onde a GUI é montada, e o código da classe TestJTextField.java onde é criado um objeto do tipo GuiJTextField, que por sua vez exibe a interface: 1 import java.awt.FlowLayout; 2 import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela 3 import javax.swing.JLabel; //classe do componente de rótulo (label). Exibe texto e imagem 4 import javax.swing.JTextField; //classe do componente de caixa de texto 5 import java.awt.event.ActionListener; //interface que trata o evento gerado pelo componente JButton 6 import java.awt.event.ActionEvent; //classe do evento gerado pelo componente de JButton 7 import javax.swing.JButton; //classe do componente botão (button) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class GuiJTextField extends JFrame{ private JLabel labelNu1; private JLabel labelNu2; private JTextField textfieldNu1; private JTextField textfieldNu2; private JTextField textfieldResult; private JLabel labelResultado; private JButton button1; public GuiJTextField(){ super(“Exemplo JTextField”); setLayout(new FlowLayout()); labelNu1 = new JLabel(“Primeiro Número”); labelNu1.setToolTipText(“Digite o primeiro número”); add(labelNu1); textfieldNu1 = new JTextField(10); add(textfieldNu1); labelNu2 = new JLabel(“Segundo Número”); labelNu2.setToolTipText(“Digite o segundo número”); add(labelNu2); textfieldNu2 = new JTextField(10); add(textfieldNu2); button1 = new JButton(“Soma”); add(button1); TrataEventoBotao trataevento = new TrataEventoBotao(); button1.addActionListener(trataevento); Unidade 2 Linguagens de Programação II.indb 49 49 7/12/2006 14:00:32 Universidade do Sul de Santa Catarina 45 labelResultado = new JLabel(“Resultado”); 46 labelResultado.setToolTipText(“Resultado da Soma”); 47 add(labelResultado); 48 49 textfieldResult = new JTextField(10); 50 textfieldResult.setEditable(false); 51 add(textfieldResult); 52 53 54 } 55 56 private class TrataEventoBotao implements ActionListener{ 57 public void actionPerformed(ActionEvent event){ 58 textfieldResult.setEditable(true); 59 textfieldResult.setText(Integer.toString(Integer. parseInt(textfieldNu1.getText())+ Integer. parseInt(textfieldNu2.getText()))); 60 61 }//fim do método 62 }//fim da classe interna 63 }//fim da classe de primeiro nível Código da classe TestJTextField.java: 1 import javax.swing.JFrame; 2 3 public class TesteJTextField{ 4 5 public static void main(String arg[]){ 6 7 GuiJTextField guijtextfield = new GuiJTextField(); 8 9 guijtextfield.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 10 guijtextfield.setSize(275,280); 11 guijtextfield.setVisible(true); 12 13 } 14 } Acompanhe a análise do código das duas classes, linha a linha: Linhas 1 a 7 – importação de todas as classes que serão utilizadas na aplicação. Note que algumas delas pertencem ao pacote java. awt e outras ao pacote javax.swing. Linha 10 – definição da classe GuiJTextField. Note que esta classe estende a classe JFrame, logo ela também é um frame. Isto faz com que a GUI tenha a aparência de uma janela. 50 Linguagens de Programação II.indb 50 7/12/2006 14:00:32 Linguagens de Programação II Linhas 12 a 18 – definição de todos os atributos ou componentes da aplicação. JLabel representa os rótulos, JTextField os campos de texto (onde o usuário entrará com os números e o resultado da soma será exibido) e JButton é o componente que acionará a soma dos dois números. Linha 21 – início do construtor da classe GuiJTextField. É dentro do construtor que será montada toda a GUI, ou seja, cria-se os componentes, adiciona-se os componentes ao frame (se GuiJTextField estende JFrame, ele também é um frame – janela), registra-se o objeto que ouve e trata o evento gerado pelo clique no botão ao componente JButton, etc. Esse construtor é chamado na classe TesteJTextField, quando um objeto desse tipo é criado (linha 7 da classe TesteJTextField). Linha 22 – chamada ao construtor da superclasse JFrame. Chamamos o construtor de qualquer superclasse sempre com super(). É enviado como argumento o texto que aparecerá na barra de título do frame (janela). Linha 23 – os componentes numa GUI são dispostos conforme um layout previamente estabelecido. Existem vários tipos de layout. Por enquanto, você utilizará o FlowLayout, explicado no código da unidade anterior. Para configurar (setar) o layout, é usado o método setLayout() e passado como argumento um objeto do tipo FlowLayout (new FlowLayout). Linhas 25 a 27 – um componente do tipo JLabel é criado, configurado o texto que será exibido quando o mouse estiver posicionado em cima desse JLabel e, logo após, o componente é adicionado ao container (frame). Linhas 29 e 30 – o primeiro componente JTextField (campo de texto) é criado. Neste componente será digitado o primeiro número. O número de colunas de texto é passado como argumento para o construtor do componente. A largura em pixels de uma coluna de texto é determinada pela largura média de um caractere, na fonte atual do campo de texto. Quando o texto exibido em um campo for mais longo que o tamanho do campo, a parte à direita do texto não ficará mais visível. Se o texto digitado exceder a borda direita do campo de texto, então parte do texto à esquerda será empurrada para fora do lado esquerdo do campo Unidade 2 Linguagens de Programação II.indb 51 51 7/12/2006 14:00:32 Universidade do Sul de Santa Catarina e não ficará mais visível. Use as setas esquerda e direita para se locomover no campo de texto. Na linha 30, o componente é adicionado ao frame. Linhas 32 a 34 – criação do segundo componente JLabel e adição dele ao frame. Linhas 36 e 37 – o segundo componente JTextField (campo de texto) é criado. Neste componente será digitado o segundo número. Logo após, ele é adicionado ao frame. Linhas 39 e 40 – o componente JButton é criado. O rótulo que será exibido no botão é passado como argumento para o construtor. Logo após, ele é adicionado ao frame. Linha 42 – nessa linha começa o processo de tratamento de evento, comentado no início desta unidade. Ele será abordado de maneira resumida neste momento, durante a explicação do código. Na seção seguinte, após a explicação de todo o código, abordaremos o processo de tratamento de evento de maneira mais detalhada. Saiba mais sobre o Tratamento de Evento Como escrito anteriormente, a interação do usuário com um componente gera eventos variados. Com isto, podemos dizer que um componente (um objeto) é onde se origina um evento (outro objeto). Este objeto de evento armazena informações sobre o evento que aconteceu, como por exemplo, a referência ao componente que originou o evento e outras informações. No processo de tratamento de um evento, existe um terceiro elemento denominado de objeto ouvinte de evento. Este objeto ouvinte de evento é notificado, avisado quando um determinado evento ocorre em um componente, mas, para isto, ele precisa ser registrado (adicionado) junto ao componente que gera eventos. Quando o objeto ouvinte de evento é registrado junto ao componente que gera eventos, o componente avisa ou notifica este objeto ouvinte de evento que ocorreu um evento e, então, esse objeto ouvinte de evento pode executar uma resposta ao evento, ou seja, executar um método com algum código em resposta a esse evento. Esse método recebe como parâmetro o objeto de evento. 52 Linguagens de Programação II.indb 52 7/12/2006 14:00:33 Linguagens de Programação II Para que esse processo ocorra, os seguintes passos são necessários: 1 – É preciso criar uma classe que “trate” o evento desejado. Essa classe será criada dentro da classe que cria a GUI. Observe a linha 56. A linguagem Java permite que sejam declaradas classes dentro de classes. Elas são chamadas de classes aninhadas. Nesse caso, essa classe é chamada também de classe interna. Este tipo de classe é freqüentemente utilizada para o tratamento de eventos. 2 – A classe interna, mencionada acima, deve implementar uma interface ouvinte de evento (listener). Você já aprendeu que uma interface é uma estrutura que pode conter somente métodos abstract (sem código). Existem várias interfaces ouvintes de eventos prontas na API do Java. Você tem que saber qual a interface apropriada para o tipo de evento que irá ocorrer. 3 – Um objeto do tipo dessa classe deve ser criado. Esse é o objeto ouvinte de evento mencionado acima. Esse objeto deve ser notificado, avisado quando o evento em um componente ocorrer. Para que ele seja avisado, é, então, necessário registrá-lo junto ao componente. Os passos descritos são demonstrados nas linhas 42 (criação do objeto ouvinte de evento), 43 (registro desse objeto junto ao componente que dispara o evento, nesse caso JButton button1) e 56 a 62 (criação da classe que trata o evento, da qual o objeto ouvinte de evento se origina). Na linha 42, um objeto do tipo TrataEventoBotao é criado. Esse é o objeto ouvinte de evento. TrataEventoBotao é classe interna mencionada no passo 1. Linha 43 – Registro do objeto ouvinte de evento junto ao componente JButton button1. Para que o objeto ouvinte de evento ouça e trate os eventos gerados por este componente, ele precisa ser registrado junto ao componente JButton button1. O objeto ouvinte de evento é registrado com o método addActionListener(). Este mesmo objeto ouvinte de evento, criado na linha 42, é passado como argumento. Linhas 45 a 47 – criação do segundo componente JLabel label 3 com o rótulo “Resultado” e adição dele ao frame. Linhas 49 a 51 – o terceiro componente JTextField (campo de texto) é criado. Nesse componente será exibido o resultado da Unidade 2 Linguagens de Programação II.indb 53 53 7/12/2006 14:00:33 Universidade do Sul de Santa Catarina soma. Na linha 50, ele é configurado para não ser editável com o método setEditable(false), ou seja, o usuário não poderá inserir dados no componente e ele servirá apenas para exibir o resultado da soma. Logo após, o componente é adicionado ao frame. Linha 54 – fim do construtor. Linha 56 – início da classe interna TrataEventoBotao. Essa é a classe responsável pelo tratamento do evento que ocorrerá quando o usuário clicar no botão. Note que o modificador de acesso da classe é private porque essa classe será utilizada para tratar eventos gerados pelos componentes definidos na classe principal, também chamada de classe de primeiro nível (GuiJTextField). Ela pode ser public, protected ou private. A classe TrataEventoBotao implementa (implements) a interface já definida na API do Java chamada ActionListener. Ela deve implementar exatamente essa interface porque o evento gerado pelo clique no botão é do tipo ActionEvent (classe ActionEvent). O que exatamente significa isso? Revisando! A interação do usuário (clicar, passar o mouse sobre, digitar caracteres, etc.) com um componente pode gerar vários tipos de eventos (objetos de evento). Uma interação específica com um componente, como clicar no botão, gera um tipo de evento específico. Cada objeto de evento é criado por uma classe que implementa uma interface específica desse tipo de evento. 54 Linguagens de Programação II.indb 54 7/12/2006 14:00:33 Linguagens de Programação II Acompanhe o exemplo: Quando o usuário clica no botão, um objeto de evento do tipo ActionEvent (classe ActionEvent) é gerado. Quando o usuário pressiona a tecla Enter num componente JTextEdit, um objeto de evento do tipo ActionEvent também é gerado. Quando o usuário digita caracteres em um campo de texto, um objeto de evento do tipo KeyEvent é gerado. Quando o usuário passa o mouse sobre um componente, um objeto de evento do tipo MouseEvent é gerado, etc. Perceba que, conforme o tipo de interação com o componente, outro tipo de evento pode ocorrer. Em outras aplicações, você trabalhará com outros tipos de eventos. O objeto de uma classe que implementa a interface ActionListener somente pode “ouvir” ou tratar eventos do tipo ActionEvent, desde que esse objeto seja registrado junto ao componente. Lembre-se que o objeto do tipo TrataEventoBotao é criado na linha 42 e, na linha 43, ele é adicionado (registrado) ao componente JButton button1. Assim, quando o usuário clicar no botão para realizar a soma, um objeto de evento do tipo ActionEvent será disparado e passado como parâmetro para o método do objeto ouvinte de evento, que foi registrado junto ao componente JButton button1. Assim, tudo o que foi programado nesse método (linhas 57 a 61) será executado. Que método é esse? Tal método é o que está dentro da classe TrataEventoBotao, já que o objeto ouvinte de evento é desse tipo. Esse método é o actionPerformed(), definido na linha 57. Unidade 2 Linguagens de Programação II.indb 55 55 7/12/2006 14:00:33 Universidade do Sul de Santa Catarina O que está programado dentro dele? A soma dos dois valores digitados nos componentes JTextField. Linha 57 – como mencionado na explicação acima, aqui começa a redefinição do método actionPerformed(). Note que o termo usado foi redefinição, pois é exatamente isso que está sendo feito, uma vez que esse método está definido como abstract na interface ActionListener. Lembre-se que, quando uma classe implementa uma interface, ela deve, obrigatoriamente, redefinir (provavelmente com código dentro) todos os métodos dessa interface. Como esse é o único método da interface ActionListener, é necessário redefinir somente ele. Note que esse método recebe como parâmetro um objeto de evento do tipo ActionEvent, porque é esse tipo de evento que é gerado quando o usuário clica no botão. Linha 58 – aqui começa a programação do que você quer que aconteça quando o usuário clicar no botão Soma. Tudo o que for programado aqui, será executado nesse momento. O que você quer que aconteça? Que os dois números digitados nos componentes JTextField sejam somados. Para isso, nessa linha o componente textfieldResult é configurado para true através do método setEditable(). Com isso, o campo torna-se editável e armazena-se o resultado da soma dentro desse componente. Linha 59 – essa linha é programada para armazenar algum valor no componente textfieldResult. Isso é feito com o método setText(). O valor que se quer armazenar é o que foi digitado e armazenado nos dois primeiros componentes JTextField. Para 56 Linguagens de Programação II.indb 56 7/12/2006 14:00:33 Linguagens de Programação II isso, são recuperados esses valores através do método getText() de cada componente JTextField. O valor retornado é do tipo String; logo, eles precisam ser transformados para int com o método Integer.parseInt(), somados e o resultado da soma transformado para String novamente, para, finalmente, ser passado como argumento para o método setText(), já que este método aceita somente dados do tipo String. Linha 61 – fim do método actionPerformed(). Linha 62 – fim da classe interna TrataEventoBotao. Linha 63 – fim da classe de primeiro nível GuiJTextField. O código da classe TesteJTextField, analisado abaixo, possui o método main() e dentro dele é criado um objeto do tipo da classe GuiJTextField. Linha 7 – Um objeto do tipo GuiJTextField é criado. Quando o construtor GuiJTextField () desse objeto é chamado, a interface é exibida porque é dentro dele que ela é programada. Linha 9 a 11 – configura o modo de fechamento da janela, o tamanho da janela e a torna visível. Atenção! Primeiramente, edite e compile a classe que representa a janela (estende JFrame, cria os componentes e adiciona eles ao frame). Logo após, edite e compile a classe que cria um objeto do tipo da classe anterior. Comando para compilar: javac <nome da classe.java> Comando para executar: java <nome da classe> Unidade 2 Linguagens de Programação II.indb 57 57 7/12/2006 14:00:34 Universidade do Sul de Santa Catarina É possível estender o exemplo anterior e criar uma espécie de calculadora. Para isso, é necessário adicionar mais três componentes JButton na classe GuiJTextField. Os outros botões representarão as ações de subtração, multiplicação e divisão. A figura 2.2 representa essa aplicação: FIGURA 2.2 – GUI DA APLICAÇÃO TESTEJTEXTFIELD O código da classe GuiJTextField é mostrado e as alterações são comentadas no decorrer do código abaixo: import java.awt.FlowLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JButton; public class GuiJTextField extends JFrame{ private JLabel labelNu1; private JLabel labelNu2; private JTextField textfieldNu1; private JTextField textfieldNu2; private JTextField textfieldResult; private JLabel labelResultado; private JButton buttonSoma; private JButton buttonSubtracao; private JButton buttonMultiplicacao; private JButton buttonDivisao; São criados mais três componentes JButton e modificado seus nomes. public GuiJTextField(){ super(“Exemplo JTextField”); setLayout(new FlowLayout()); labelNu1 = new JLabel(“Primeiro Numero”); labelNu1.setToolTipText(“Digite o primeiro número”); add(labelNu1); 58 Linguagens de Programação II.indb 58 7/12/2006 14:00:34 Linguagens de Programação II textfieldNu1 = new JTextField(5); add(textfieldNu1); labelNu2 = new JLabel(“Segundo Numero”); labelNu2.setToolTipText(“Digite o segundo número”); add(labelNu2); textfieldNu2 = new JTextField(10); add(textfieldNu2); buttonSoma = new JButton(“Soma”); add(buttonSoma); buttonSubtracao = new JButton(“Subtração”); add(buttonSubtracao); buttonMultiplicacao = new JButton(“Multiplicação”); add(buttonMultiplicacao); buttonDivisao = new JButton(“Divisao”); add(buttonDivisao); TrataEventoBotao trataevento = new TrataEventoBotao(); buttonSoma.addActionListener(trataevento); buttonSubtracao.addActionListener(trataevento); buttonMultiplicacao.addActionListener(trataevento); buttonDivisao.addActionListener(trataevento); labelResultado = new JLabel(“Resultado”); labelResultado.setToolTipText(“Resultado da Soma”); add(labelResultado); textfieldResult = new JTextField(10); textfieldResult.setEditable(false); add(textfieldResult); } .. .. Os quatro componentes JButton são criados e adicionados ao frame um após o outro O objeto ouvinte de evento é criado. Logo após, este mesmo objeto é registrado junto aos quatro componentes JButton. Isto significa que quando um evento for disparado por causa da interação do usuário em qualquer dos componentes, o mesmo objeto ouvinte de evento irá tratar esse evento. Você verá mais detalhes na explicação do código da classe TrataEventoBotao. Note que o código do método actionPerformed() foi bastante alterado. Isto aconteceu porque precisamos saber qual o componente que originou o evento. Você verá mais explicações após o código. 63 private class TrataEventoBotao implements ActionListener{ 64 public void actionPerformed(ActionEvent event){ 65 textfieldResult.setEditable(true); 66 if (event.getSource() == buttonSoma) 67 textfieldResult.setText(Integer.toString(Integer.parseInt(textfieldNu1.getText())+ Integer.parseInt(textfieldNu2.getText()))); 68 else 69 if (event.getSource() == buttonSubtracao) 70 textfieldResult.setText(Integer.toString(Integer.parseInt(textfieldNu1.getText())Integer.parseInt(textfieldNu2.getText()))); 71 else 72 if (event.getSource() == buttonMultiplicacao) 73 textfieldResult.setText(Integer.toString(Integer.parseInt(textfieldNu1.getText())* Integer.parseInt(textfieldNu2.getText()))); 74 else 75 if (event.getSource() == buttonDivisao) 76 textfieldResult.setText(Integer.toString(Integer.parseInt(textfieldNu1.getText())/ Integer.parseInt(textfieldNu2.getText()))); 77 } //fim do método 78 } //fim da classe interna 79 } //fim da classe inicial Unidade 2 Linguagens de Programação II.indb 59 59 7/12/2006 14:00:34 Universidade do Sul de Santa Catarina O código da classe interna TrataEventoBotao será explicado abaixo: Linha 63 – essa é numeração é sugerida para início da classe interna TrataEventoBotao. Você já sabe que essa classe somente tratará eventos do tipo ActionEvent, pois ela implementa somente a interface ActionListener; dizemos somente porque uma classe pode implementar mais de uma interface, lembra? Mas esse não é o caso dessa aplicação, pois nela é preciso tratar somente eventos do tipo ActionEvent, que são disparados quando o usuário clica com o mouse em algum JButton. Como agora existem quatro componentes JButton na aplicação e todos foram registrados com o mesmo objeto ouvinte de evento (objeto do tipo TrataEventoBotao). Se não se verificar qual o componente que originou o evento, o mesmo código programado dentro do método actionPerformed() será executado quando o usuário clicar no botão Soma, Subtração, Divisão e Multiplicação. Não se quer isto. Quer-se que quando o usuário clique no botão Soma, os dois números digitados sejam somados, e quando o usuário clicar no botão Multiplicação, os dois números sejam multiplicados, etc. Linha 64 – início do método actionPerformed(). Esse método recebe como parâmetro uma referência (lembre-se que a referência é o endereço de algum objeto na memória) ao objeto do tipo ActionEvent, gerado quando o usuário clica em algum JButton. Essa referência é armazenada na variável event. O nome dessa variável pode mudar. Esse objeto contém informações como qual o componente que originou o evento. Então, é ele, na verdade, a variável referência que será usada para saber qual o componente JButton que originou o evento. 60 Linguagens de Programação II.indb 60 7/12/2006 14:00:34 Linguagens de Programação II Linha 66 – para saber qual o componente que originou o evento, é preciso obter a referência do componente que o originou, através do método getSource() desse evento. Logo, event.getSource() retornará a referência do objeto componente que originou o evento. É preciso verificar se essa referência (endereço) é igual (=) à referência armazenada em cada uma das variáveis que guardam as referências dos quatro componentes JButton (buttonSoma, buttonSubtracao, buttonMultiplicacao, buttonDivisao). Se forem iguais, é porque esse componente originou o evento. Dentro do teste (if ) é programada a tarefa adequada. Por exemplo, se for o componente buttonSoma, então uma soma é programada. Seção 3 – Tipos de Eventos GUI e suas Interfaces Você já leu, anteriormente, que existem vários tipos de eventos (não somente ActionEvent) que podem ocorrer quando o usuário interage com um componente GUI. As informações sobre esse evento (objeto de evento) são armazenadas em um objeto (todo o objeto deriva de uma classe) que estende a classe AWTEvent. Veja que nas linhas de importação da classe GUIJTextField foi importado a classe ActionEvent do pacote java.awt.event. Essa classe estende (é uma subclasse de) AWTEvent. A figura 2.3, logo a seguir, ilustra a hierarquia de classes a partir da classe AWTEvent. Todas essas classes representam todos os tipos de objetos de evento que podem ocorrer quando o usuário interage com um componente GUI. Nas próximas aplicações, você trabalhará com muitos desses eventos. Unidade 2 Linguagens de Programação II.indb 61 61 7/12/2006 14:00:34 Universidade do Sul de Santa Catarina FIGURA 2.3 – HIERARQUIA DAS CLASSES DE EVENTOS Para cada tipo de objeto de evento, há uma interface ouvinte de evento apropriada. Para tratar esse evento, um objeto ouvinte de evento ou a classe dele precisa implementar a interface correspondente ao tipo de evento que ocorreu. No caso da aplicação anterior, já se sabia que o evento era do tipo ActionEvent. Logo, a interface que a classe do objeto ouvinte de evento teve que implementar foi ActionListener (veja a linha 63). A figura, abaixo, mostra um conjunto de interfaces definidas no pacote java.awt.event. Outras interfaces são declaradas no pacote java.swing.event. 62 Linguagens de Programação II.indb 62 7/12/2006 14:00:35 Linguagens de Programação II FIGURA 2.4 – HIERARQUIA DE INTERFACES Cada interface ouvinte de eventos especifica um ou mais métodos de tratamento de evento que devem ser declarados (redefinidos) na classe que implementa a interface. A interface ActionListener só especifica um método, ActionPerformed(), por isso, só é preciso redefinir esse método. Um componente pode ter vários tipos de objeto ouvinte de evento registrados. No caso da aplicação anterior, só tinha um tipo de objeto ouvinte de evento registrado para cada componente. Unidade 2 Linguagens de Programação II.indb 63 63 7/12/2006 14:00:35 Universidade do Sul de Santa Catarina Quando o evento ocorre, o componente GUI que o usuário interagiu notifica (avisa) todos os seus objetos ouvintes de eventos (se houver mais de um registrado). Estes, depois de notificados, executam o método apropriado (aquele que foi definido dentro da sua classe). Na próxima seção, você entenderá mais a fundo como esse mecanismo de tratamento de evento funciona. Seção 4 – Entendendo o Tratamento de Eventos Nesta seção, você verá como funciona internamente, em memória, o mecanismo de tratamento de eventos, com base no último código da aplicação mostrada nesta unidade. Nessa aplicação, existem quatro componentes JButton que geram eventos do tipo ActionEvent quando o usuário clica no botão. Existe apenas um objeto ouvinte de evento para tratar os eventos dos quatro componentes, e ele foi registrado através do método addActionListener(), para cada um dos componentes. Quando o evento ocorrer em determinado componente, o objeto ouvinte de evento é notificado e responde executando o método implementado na sua classe (actionPerformed()). Depois dessa breve revisão, faz-se necessário tentar responder duas perguntas: Como funciona o registro de um objeto ouvinte de evento em determinado objeto componente (observe que se fala no termo componente, mas todo o componente é um objeto)? Se é possível registrar vários tipos de ouvinte de evento em um componente (lembre-se que, para cada tipo evento que um componente dispara, existe um objeto ouvinte de evento apropriado), como o método correto será chamado? 64 Linguagens de Programação II.indb 64 7/12/2006 14:00:35 Linguagens de Programação II Para responder a essas perguntas e entender como o tratamento de evento ocorre, você deve observar, atentamente, a figura 2.5, em função da qual é mostrado como o tratamento ocorre para o componente JButton buttonSoma. O mesmo acontece para os demais componentes. Variável referência buttonSoma Variável referência trataevento Área dos objetos Objeto TrataEventoBotao Objeto JButton public void actionPerformed(ActionEvent event){ //tratamento do evento var. de instância listenerList } Objeto EventListenerList Essa referência é criada pela instrução buttonSoma.addActionListener(trataevento) FIGURA 2.5 – Processo de tratamento de evento em memória Note que existe uma área dos objetos e uma área para as variáveis referência, que guardam a referência (endereço) dos objetos. Na área das variáveis referência, existem duas variáveis referência: buttonSoma e trataevento. Acompanhe cada variável referência em detalhe: buttonSoma é a variável referência que guarda a referência para um componente objeto JButtom. trataevento é a variável referência que guarda a referência para o objeto ouvinte de evento do tipo TrataEventoBotao. Unidade 2 Linguagens de Programação II.indb 65 65 7/12/2006 14:00:35 Universidade do Sul de Santa Catarina Lembre-se que na disciplina de POO foi ensinado que um objeto ocupa uma determinada área da memória e, para que esse objeto seja acessado, é necessário que exista uma variável referência que guarde a sua referência (endereço). Na área dos objetos existem três objetos do tipo: JButton, TrataEventoBotao e EventListenerList. Veja cada um dos objetos abordados, em detalhe: Dentro do objeto JButton existem várias variáveis de instância ou atributos para configurar esse tipo de objeto e, também, existe uma variável de instância chamada listenerList. O mesmo acontece com qualquer tipo de objeto componente. Essa variável sempre armazena uma referência para o objeto do tipo EventListenerList. Nesse objeto do tipo EventListenerList serão armazenadas as referências (endereços) para todos os objetos ouvintes de eventos que forem criados e registrados junto ao componente (no caso da aplicação anterior, só adicionamos um). Entenda esse objeto como um array (vetor), onde cada posição armazena a referência para um determinado objeto ouvinte de evento. O objeto TrataEventoBotao terá os atributos e métodos definidos na sua classe. No caso dessa aplicação, somente o método actionPerformed(). Depois das explicações, referentes à figura anterior, existem mais elementos para responder às duas perguntas formuladas. 1) Como um objeto ouvinte de evento é registrado? Primeiramente, ele precisa ser criado (instanciado). Na aplicação, isso é feito com a instrução TrataEventoBotao trataevento = new TrataEventoBotao(); e trataevento é a variável referência do objeto TrataEventoBotao. Logo após, ele é registrado (adicionado) junto ao componente buttonSoma, com a instrução buttonSoma.addActionListener( trataevento). Quando essa instrução for executada, a referência 66 Linguagens de Programação II.indb 66 7/12/2006 14:00:35 Linguagens de Programação II do objeto ouvinte de evento TrataEventoBotao é adicionada na variável (array) de instância listenerList do componente buttonSoma. Com esse mecanismo, outros tipos de objetos ouvintes de evento podem ser adicionados a um componente GUI. Ou seja, cada componente mantém sua própria lista de objetos ouvinte de eventos que tratam os eventos do componente. 2) Se houver vários objetos ouvintes de evento adicionados no componente e cada um deles puder possuir um ou mais métodos, qual o método correto que deverá ser executado? Lembre-se que é dentro de algum método do objeto ouvinte de evento que o processamento que deve ser executado está implementado, como, por exemplo, o processamento da soma, subtração da aplicação exemplo. O que determina qual método será executado é o tipo de evento que foi gerado. Quando um evento ocorre, o objeto deste evento é passado como argumento somente para os métodos dos objetos ouvinte de evento que aceitam este tipo de objeto de evento. Acompanhe o exemplo: Quando um evento do tipo ActionEvent ocorre em um componente e esse componente tem registrados vários tipos de objetos ouvintes de evento - como MouseEvents (eventos que ocorrem quando o usuário interage no componente com o mouse, como passar o mouse em cima do componente, etc), KeyEvents (eventos que acontecem quando o usuário digita caracteres em algum componente, como no caso de um componente do tipo JTextField) e ActionEvents, quais os objetos ouvintes de evento que possuem método que aceitem uma referência a um objeto do tipo ActionEvent como parâmetro? Somente os objetos ouvintes de evento que implementam a interface ActionListener. Olhe na figura 2.5 e veja que o método desse tipo de objeto aceita um parâmetro do tipo ActionEvent. Logo, somente esse método será executado. Unidade 2 Linguagens de Programação II.indb 67 67 7/12/2006 14:00:36 Universidade do Sul de Santa Catarina Síntese No transcorrer desta unidade, você aprendeu o processo de tratamento de evento de uma GUI. Você deve estar achando este assunto muito complicado. Concordamos com você! Portanto, a dica é a mesma do início da unidade: releia quantas vezes forem necessárias para o seu entendimento. Além disto, busque as fontes de informação extra, encontradas no final desta unidade. Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Desenvolva o seguinte programa utilizando uma GUI com os componentes JTextField, JLabel e JButton aprendidos até o momento. O programa deve permitir que o usuário entre com 3 notas. Ao clicar no botão Média, a média deve ser calculada e apresentada num componente JLabel. Além disto, a situação do aluno - “Aprovado” se a média for maior ou igual a 7, “Exame” se a média for maior ou igual a 2 e menor que 7 e “Reprovado” se a média for menor que 2 - deve ser apresentada em outro componente JLabel. 68 Linguagens de Programação II.indb 68 7/12/2006 14:00:36 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando a seguinte referência, principalmente os capítulos 10, 11 e 22: DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. Consulte também: HORSTMANN, Cay; CORNELL, Gary. Core JAVA 2. Volume I – Fundamentos. 7 ed. Editora Alta Books, 2005. Consulte, também, o seguinte site: http://www.inf.pucrs.br/~flash/lapro2/lapro2_eventos.pdf (Tratamento de eventos) Unidade 2 Linguagens de Programação II.indb 69 69 7/12/2006 14:00:36 Linguagens de Programação II.indb 70 7/12/2006 14:00:36 UNIDADE 3 Componentes de uma GUI (JCheckBox, JRadioButton, JComboBox e JList) 3 Objetivos de aprendizagem Desenvolver uma GUI com o componente JCheckBox. Desenvolver uma GUI com o componente JRadioButton. Desenvolver uma GUI com o componente JComboBox. Desenvolver uma GUI com o componente JList. Seções de estudo Seção 1 Componente JCheckBox Seção 2 Componente JRadioButton Seção 3 Componente JComboBox Seção 4 Componente JList Linguagens de Programação II.indb 71 7/12/2006 14:00:36 Universidade do Sul de Santa Catarina Para início de conversa A partir desta unidade, você começa a conhecer e trabalhar com outros componentes GUI que geram outros tipos de eventos. Você já tem o conhecimento básico necessário para isso, ou seja, você já sabe que uma GUI é composta por vários componentes e que a interação com esses componentes gera eventos que precisam ser tratados. Nesta unidade, serão apresentados quatro componentes novos: JCheckBox, JRadioButton, JComboBox e JList. Está curioso e quer começar? Seção 1 – Componente JCheckBox O componente JCheckBox é conhecido como componente caixa de seleção, pois sua interface exibe um pequeno quadro, onde o usuário pode selecionar (check) ou desmarcar a opção. Quando o usuário interage com esse componente, ele mantém um estado interno selecionado ou não selecionado. Normalmente, esse componente é utilizado em situações onde o usuário pode marcar, escolher ou selecionar várias opções. Saiba mais sobre o componente JCheckBox! Consulte a documentação contida no site: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JCheckBox.html O usuário poderá interagir com os componentes JCheckBox marcando ou desmarcando as opções existentes. Quando um componente JCheckBox é marcado, o símbolo aparece e o estado do componente é configurado para selecionado. Se o usuário interage novamente, o símbolo 72 Linguagens de Programação II.indb 72 7/12/2006 14:00:36 Linguagens de Programação II desaparece e o estado do componente é configurado para não selecionado. A figura 3.1, a seguir, mostra uma GUI onde existe: um componente JTextField com um texto fornecido pela aplicação; dois componentes JCheckBox, rotulados com Negrito e Itálico. JCheckBox FIGURA 3.1 – GUI DA APLICAÇÃO TESTEJCHECKBOX Ao selecionar o componente JCheckBox Negrito, o texto será marcado com o estilo Negrito; ao selecionar o JCheckBox Itálico, o texto também será transformado para Itálico. Ao se desmarcar um dos estilos, este estilo é retirado do texto. A seguir, é exibido o código fonte da aplicação com a classe GuiJCheckBox e a classe TesteJCheckBox, referente à figura anterior. 0 1 2 3 4 import java.awt.FlowLayout; import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JTextField; //classe do componente campo de texto import javax.swing.JCheckBox; //classe do componente de caixa de seleção import java.awt.event.ItemListener; //interface para tratamento do evento do componente JCheckBox 5 import java.awt.event.ItemEvent; //classe do evento gerado pelo componente JCheckBox 6 import java.awt.Font; //classe que representa as configurações de fonte do texto exibido no JTextField 7 8 public class GuiJCheckBox extends JFrame{ 9 10 private JTextField textfield; 11 private JCheckBox checkNegrito; 12 private JCheckBox checkItalico; Unidade 3 Linguagens de Programação II.indb 73 73 7/12/2006 14:00:37 Universidade do Sul de Santa Catarina 13 14 public GuiJCheckBox(){ 15 super(“Exemplo JCheckBox”); 16 setLayout(new FlowLayout()); //configura o layout do frame 17 18 textfield = new JTextField(“Tecnologo em Web Design e Programação”); 19 textfield.setFont(new Font(“Serif”, Font.PLAIN, 14)); 20 add(textfield); //adiciona textfield ao frame 21 22 checkNegrito = new JCheckBox(“Negrito”);//cria o primeiro componente JCheckBox 23 checkItalico = new JCheckBox(“Italico”);//cria o segundo componente 24 add(checkNegrito);//adiciona os dois componentes ao frame 25 add(checkItalico); 26 27 //cria o objeto ouvinte de evento 28 TrataEventoCheckBox trataevento = new TrataEventoCheckBox(); 29 //adiciona esse objeto a cada um dos componentes. Veja que o método agora é addItemListener() 30 checkNegrito.addItemListener(trataevento); 31 checkItalico.addItemListener(trataevento); 32 33 34 } 35 36 private class TrataEventoCheckBox implements ItemListener{ 37 private int valorNegrito = Font.PLAIN; //controla o estilo da fonte Negrito 38 private int valorItalico = Font.PLAIN; //controla o estilo da fonte Itálico 39 40 public void itemStateChanged(ItemEvent event){ 41 42 //verifica a origem do evento. Trata o evento para o componente checkNegrito 43 if (event.getSource() == checkNegrito){ 44 if (checkNegrito.isSelected()) 45 valorNegrito = Font.BOLD; 46 else 47 valorNegrito = Font.PLAIN; 48 } 49 50 //verifica a origem do evento. Trata o evento para o componente checkItalico 51 if (event.getSource() == checkItalico){ 52 if (checkItalico.isSelected()) 53 valorItalico = Font.ITALIC; 54 else 55 valorItalico = Font.PLAIN; 56 } 57 58 textfield.setFont(new Font(“Serif”,valorNegrito + valorItalico,14)); 59 } 60 } 61 } 74 Linguagens de Programação II.indb 74 7/12/2006 14:00:37 Linguagens de Programação II Acompanhe o comentário de algumas linhas do código anterior: Linha 18 – criação do componente de texto JTextField. O texto “Tecnólogo em Web Design e Programação” é passado para o construtor desse componente. Esse procedimento faz com que esse texto apareça dentro do componente. Linha 19 – o método setFont() do componente JTextField é invocado para fazer a configuração da fonte (nome da fonte, estilo da fonte, tamanho) do texto que será exibido. Esse método deve recebe a referência de um novo objeto do tipo Font (veja que essa classe está sendo importada na linha 6). Por isso, o argumento passado é new Font(“Serif ”, Font.PLAIN, 14)). Note que, no construtor de Font, são passados como argumento o nome da fonte (“Serif ”), o estilo da fonte (Font.PLAIN) e o tamanho (14). Font.PLAIN é um atributo int static da classe Font. Consulte a documentação dessa classe Font e você verá que existem outros estilos que podem ser utilizados. Para tanto, pesquise em: http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Font. html Linha 22 e 23 – criação dos componentes JCheckBox. No construtor, o texto é passado, isto é, o rótulo que aparece do lado direito da caixa de seleção. Linha 28 – quando o usuário clica num componente JCheckBox, um evento do tipo ItemEvent (classe ItemEvent é importada na linha 5) é gerado. Note que, agora, o evento não é mais ActionEvent. Outro tipo de evento será tratado nessa aplicação. Esse evento deve ser tratado por um objeto ouvinte de evento do tipo ItemListener, ou seja, que implementa a interface ItemListener (importada na linha 4), dentro do método itemStateChanged(). Assim, essa linha cria um objeto ouvinte de evento do tipo TrataEventoCheckBox. Essa é a classe interna que implementa a interface ItemListener (linha 36). Linha 29 e 30 – adiciona o objeto ouvinte de evento aos dois componentes JCheckBox, através do método addItemListener(). Unidade 3 Linguagens de Programação II.indb 75 75 7/12/2006 14:00:37 Universidade do Sul de Santa Catarina Note que se o evento mudar, a interface do objeto ouvinte de evento e o método que adiciona o objeto ouvinte ao componente também mudarão. Linha 36 – início da classe interna TrataEventoCheckBox que implementa a interface ItemListener. Linha 37 e 38 – criação de duas variáveis de instância da classe TrataEventoCheckBox. Ambas são do tipo int. Essas duas variáveis irão controlar o estilo de formatação Negrito e Itálico. Ao serem declaradas, elas recebem o valor inteiro do estilo PLAIN (simples), estilo sem formatação. Linha 40 – início do método itemStateChanged(). Esse método é abstract na interface ItemListener e precisa ser redefinido nessa classe. Esse método recebe como parâmetro uma referência ao objeto de evento ItemEvent, gerado quando o usuário interagir com algum componente JCheckBox. Essa referência é armazenada na variável chamada event (o nome dessa variável pode mudar). É nesse método que será controlada a interação do usuário com os componentes JCheckBox checkNegrito e JCheckBox checkItalico. Linha 43 – testa a origem do evento, ou seja, qual o componente que originou o evento. Esse teste já foi explicado com detalhes na aplicação da unidade anterior. É preciso fazer este teste porque o mesmo objeto ouvinte de evento foi registrado junto aos dois componentes JCheckBox. Assim, quando o usuário interagir com algum JCheckBox, o evento ItemEvent ocorrerá e será enviado para o método itemStateChanged(). Linha 44 – se for o componente checkNegrito que originou o evento, é necessário testar, também, se o componente foi selecionado (marcado) ou não. Esse teste é feito com o método isSelected() do componente checkNegrito. Esse método retorna true se o componente foi selecionado. Linhas 45 a 47 – se o componente checkNegrito foi selecionado, então o valor do atributo Font.BOLD é armazenado na variável valorNegrito. Senão, o valor do atributo Font.PLAIN é armazenado nessa variável. 76 Linguagens de Programação II.indb 76 7/12/2006 14:00:37 Linguagens de Programação II Linhas 51 a 56 – a mesma verificação acontece para o componente checkItalico. Só que as configurações são armazenadas na variável valorItalico. Linha 58 – o método setFont() muda as configurações de fonte do texto no componente JTextField textfield. O argumento passado é a referência de um novo objeto do tipo Font. Esse objeto do tipo Font mantém o mesmo nome e tamanho de fonte, mas o estilo é a soma do conteúdo das variáveis valorNegrito + valorItalico. A seguir, é apresentado o código fonte da classe TesteJCheckBox. Esse código é semelhante ao código fonte da classe TestJTextField da unidade anterior. import javax.swing.JFrame; public class TesteJCheckBox{ public static void main(String arg[]){ GuiJCheckBox guijcheckbox = new GuiJCheckBox(); guijcheckbox.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guijcheckbox.setSize(275,280); guijcheckbox.setVisible(true); } } Caro aluno, edite e compile a classe GuiJCheckBox. Logo após, edite, compile e execute a classe TesteJCheckBox. 1.1 – Outros métodos de JCheckBox A classe JCheckBox possui outros métodos interessantes que podem ser usados no desenvolvimento de umaGUI: void setEnabled(boolean b) – marca o JCheckBox. void setTex(String text) – seta o label do JCheckBox. Unidade 3 Linguagens de Programação II.indb 77 77 7/12/2006 14:00:37 Universidade do Sul de Santa Catarina Seção 2 – Componente JRadioButton O componente JRadioButton, também conhecido como botão de radio, é um componente que também mantém um estado interno selecionado ou não selecionado. Normalmente, esse componente é utilizado com outros componentes JRadioButton, dentro de um grupo no qual somente uma opção deve ser escolhida, ou seja, um JRadioButton é selecionado. Assim, quando um componente é selecionado, o outro é desmarcado automaticamente. Saiba mais sobre o componente JRadioButton! Consulte a documentação em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JRadioButton.html A figura 3.2 mostra a GUI de uma aplicação semelhante à anterior. Contudo, nesse caso, o usuário poderá escolher somente uma entre as quatro opções que representam os estilos que podem ser aplicados ao texto no JTextField. JRadioButton FIGURA 3.2 – GUI DA APLICAÇÃO TESTEJRADIOBUTTON 78 Linguagens de Programação II.indb 78 7/12/2006 14:00:38 Linguagens de Programação II O código, abaixo, é da classe GuiJRadioButton. 1 2 3 4 5 6 7 import java.awt.FlowLayout; //classe do gerenciador de layout import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JTextField; //classe do componente de texto import javax.swing.JRadioButton; //classe do componente botão de rádio import javax.swing.ButtonGroup; //classe do agrupador de botões de rádio import java.awt.event.ItemListener; //interface que trato o evento desse componente import java.awt.event.ItemEvent; //classe do evento gerado pelo componente JRadioButton 8 import java.awt.Font; 9 10 public class GuiJRadioButton extends JFrame{ 11 12 private JTextField textfield; 13 private Font fontNegrito; 14 private Font fontItalico; 15 private Font fontSimples; 16 private Font fontNegritoItalico; 17 private JRadioButton radioNegrito; 18 private JRadioButton radioItalico; 19 private JRadioButton radioSimples; 20 private JRadioButton radioNegritoItalico; 21 private ButtonGroup grupoRadio; 22 23 public GuiJRadioButton(){ 24 super(“Exemplo JRadioButton”); 25 setLayout(new FlowLayout()); //configura o layout do frame 26 27 textfield = new JTextField(“Tecnólogo em Web Design e Programação”); 28 textfield.setFont(new Font(“Serif”, Font.PLAIN, 14)); //configura o tipo da fonte, estilo e tamanho 29 add(textfield); //adiciona textfield ao frame 30 31 radioNegrito = new JRadioButton(“Negrito”);//cria o primeiro componenteJRadioButton 32 radioItalico = new JRadioButton(“Italico”);//cria o segundo componente 33 radioSimples = new JRadioButton(“Simples”);//cria o terceiro componente 34 radioNegritoItalico = new JRadioButton(“Negrito + Italico”);//cria o quarto componente 35 add(radioNegrito);//adiciona os quatro componentes ao frame 36 add(radioItalico); 37 add(radioSimples); 38 add(radioNegritoItalico); 39 40 grupoRadio = new ButtonGroup(); //cria ButtonGroup - componente agrupador dos botões de radio 41 grupoRadio.add(radioNegrito); //adiciona cada JRadioButton ao ButtonGroup 42 grupoRadio.add(radioItalico); 43 grupoRadio.add(radioSimples); 44 grupoRadio.add(radioNegritoItalico); 45 //cria quatro objeto do tipo Font. Servirãopara configurar o texto do JTextField 46 fontNegrito = new Font(“Serif”, Font.BOLD, 14); 47 fontItalico = new Font(“Serif”, Font.ITALIC, 14); 48 fontSimples = new Font(“Serif”, Font.PLAIN, 14); // JTextField 49 fontNegritoItalico = new Font(“Serif”, Font.BOLD+Font.ITALIC, 14); 50 textfield.setFont(fontSimples); Unidade 3 Linguagens de Programação II.indb 79 79 7/12/2006 14:00:38 Universidade do Sul de Santa Catarina 51 //cria um objeto ouvinte de evento novo para cada componente e o adiciona ao componente JCheckBox através do método addItemListener radioNegrito.addItemListener(new TrataEventoRadio(fontNegrito)); radioItalico.addItemListener(new TrataEventoRadio(fontItalico)); radioSimples.addItemListener(new TrataEventoRadio(fontSimples)); radioNegritoItalico.addItemListener(new TrataEventoRadio(fontNegritoItalico)); 52 53 54 55 56 57 } //fim do construtor 58 private class TrataEventoRadio implements ItemListener{ 59 private Font fonte; //variável de instância do tipo Font 60 61 public TrataEventoRadio(Font f){ //construtor da classe 62 fonte = f; 63 } 64 65 public void itemStateChanged(ItemEvent event){ 66 textfield.setFont(fonte); //configura a fonte do texto no JTextField 67 } 68 } //fim da classe interna 69 } //fim da classe de primeiro nível Veja a explicação do código acima. Linha 40 – criação de um objeto do tipo ButtonGroup. Esse objeto tem a função de agrupar todos os componentes JRadioButton e controlar para que somente um componente seja selecionado por vez. Ele não é considerado um componente GUI e não é exibido visualmente na GUI. O primeiro JRadioButton adicionado ao grupo aparecerá como selecionado. Linha 41 a 44 – todos os componentes JRadioButton são adicionados, através do método add(), ao objeto ButtonGroup. Linha 46 a 49 – criação de quatro objetos do tipo Font. Cada um deles com um estilo diferente. Linha 50 – a referência do objeto Font com estilo PLAIN (sem estilo) armazenada na variável fontePlain é passada como argumento para o método setFont(). Assim, o texto no componente JTextField fica sem estilo (limpo). Linha 52 a 55 – nessa aplicação é criado e registrado um novo objeto ouvinte de evento para cada componente JRadioButton. Este procedimento difere das outras aplicações, onde um único objeto ouvinte de evento foi criado e registrado para todos os 80 Linguagens de Programação II.indb 80 7/12/2006 14:00:38 Linguagens de Programação II componentes. Componentes JRadioButton também geram objetos de evento do tipo ItemEvent ( o mesmo de JCheckBox). Logo, a classe do objeto ouvinte de evento também deve implementar a interface ItemListener. A classe que implementa a interface ItemListener é chamada de TrataEventoRadio e, por isso, o objeto ouvinte de evento é desse tipo. Nessas linhas, a instrução new TrataEventoRadio (fontNegrito) cria um objeto ouvinte de evento e chama seu construtor passando a referência de algum objeto Font criado nas linhas 46 a 49 e configurado para o estilo que o objeto JRadioButton representa. A referência do novo objeto ouvinte de evento é passada para o método addItemListener() de cada componente JRadioButton. Esse método faz o registro do objeto ouvinte de evento ao componente. Linha 58 – início da classe interna TrataEventoRadio que implementa a interface ItemListener. Linha 59 – declaração de uma variável de instância do tipo Font. Essa variável armazenará a referência de um algum objeto Font. Linha 61 a 63 – início do método construtor da classe que trata o evento. Essa é a primeira vez que é programado um construtor na classe tratadora de evento. Ele é chamado toda vez que um objeto ouvinte de evento é criado (veja linhas 52 a 55). Esse método recebe como parâmetro uma referência a algum objeto do tipo Font, criado nas linhas 46 a 49. Essa referência é armazenada na variável f. O conteúdo dessa variável f é armazenado na variável de instância fonte, criada na linha 59. Esse procedimento faz com que cada objeto ouvinte de evento guarde um valor próprio (na variável fonte) de configuração de fonte de texto. Quando o evento do componente JRadioButton ocorrer, o método itemStateChanged() do objeto de evento específico, associado àquele componente, será chamado e o que foi programado dentro dele será executado. Linha 65 a 67 – início do método itemStateChanged(). A única linha dentro desse método configura o texto do componente JTextField através do método setFont(). O conteúdo da variável Unidade 3 Linguagens de Programação II.indb 81 81 7/12/2006 14:00:38 Universidade do Sul de Santa Catarina de instância fonte é passado como parâmetro. Você sabe o que está dentro dessa variável? A referência de algum objeto Font que foi passada para ela quando o objeto ouvinte de evento foi criado. Por exemplo, se o usuário clicar no JRadioButton radioNegrito. o texto será configurado para o estilo Negrito porque, quando o objeto ouvinte de evento desse componente foi criado, foi passado para o seu construtor a referência de algum objeto Font configurado para Negrito (veja linha 52). Essa referência foi armazenada na variável fonte desse objeto ouvinte de evento. Quando o evento ocorrer nesse componente, o método itemStateChanged() será chamado e, dentro dele, a instrução que configura o texto do campo de texto receberá a configuração armazenada na variável fonte. O código da classe TesteJRadioButton é exibido abaixo: import javax.swing.JFrame; public class TesteJRadioButton{ public static void main(String arg[]){ GuiJRadioButton guijradio = new GuiJRadioButton(); guijradio.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guijradio.setSize(275,280); guijradio.setVisible(true); } } Caro aluno, edite e compile a classe GuiJRadioButton. Edite, compile e execute a classe TesteJRadioButton. Seção 3 – Componente JComboBox O componente JComboBox, conhecido como caixa de combinação ou caixa drop-down, fornece uma lista de itens das quais o usuário pode escolher uma única opção. Essa lista aparece quando a seta é clicada com o mouse. A interação do usuário com esse componente gera o objeto de evento do tipo ItemEvent, assim como JCheckBox e JRadioButton. 82 Linguagens de Programação II.indb 82 7/12/2006 14:00:39 Linguagens de Programação II Saiba mais sobre o componente JComboBox! Consulte a documentação referente a este componente em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JComboBox.html A figura 3.3 mostra a GUI de uma aplicação, em que você deve escolher um entre vários nomes de cores disponíveis. Ao escolher um item, a cor de fundo do frame é modificada para a cor que você escolheu. JComboBox FIGURA 3.3 – GUI DA APLICAÇÃO TESTEJCOMBOBOX O código abaixo se refere à classe GuiJComboBox. 1 import javax.swing.*; //import que possibilita a utilização de todas as classes desse pacote 2 import java.awt.*; 3 import java.awt.event.*; 4 5 public class GuiJComboBox extends JFrame { 6 private JComboBox listadecores; //componente JComboBox 7 private String nomesCor[] = {“Preto”, “Azul”, “Ciano”, “CinzaEscuro”, “Cinza”, “Verde”, “Cinza Claro”,”Magenta”, “Laranja”, “Rosa”, “Vermelho”, “Branco”, “Amarelo” }; //array criado e inicializado com o nome das cores 8 private Color cores[] = {Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Unidade 3 Linguagens de Programação II.indb 83 83 7/12/2006 14:00:39 Universidade do Sul de Santa Catarina Color.lightGray, Color.magenta, Color.orange,Color.pink, Color.red,Color.white, Color.yellow }; //array do tipo Color 9 10 public GuiJComboBox() { 11 super(“Exemplo JComboBox”); 12 setLayout( new FlowLayout() ); //configura o gerenciador de layout FlowLayout 13 listadecores = new JComboBox( nomesCor ); 14 listadecores.setMaximumRowCount( 13 ); 15 add( listadecores ); //adiciona o JComboBox ao frame 16 17 TratadorComboBox tratacombo = new TratadorComboBox(); //cria o objeto ouvinte de evento 18 listadecores.addItemListener(tratacombo); //registra o objeto ouvinte ao componente 19 20 getContentPane().setBackground(cores[0]); //configura cor do frame para a primeira cor do array cores, no caso, a cor preto. 21 } 22 23 private class TratadorComboBox implements ItemListener{ 24 public void itemStateChanged(ItemEvent e){ 25 getContentPane().setBackground(cores[listadecores.getSelectedIndex() ] ); 26 } 27 } 28 29 }//fim da classe GuiJComboBox Acompanhe, agora, a explicação deste código: Linha 6 – cria o componente JComboBox. Linha 7 – declara e inicializa um array de Strings chamado nomecores[] com os nomes das cores. Note que o nome de cada cor é uma String, por isso está em “ ”. Linha 8 – declara e inicializa um array de objetos do tipo Color (classe Color do pacote java.awt) chamado cores. Cada cor é representada por um objeto diferente. Ex. Color.black é o objeto Color que representa a cor preta. Linha 13 – o componente JComboBox é criado. O array do tipo String com o nome das cores é passado como argumento para o seu construtor. Linha 14 – o número de itens (linhas) que aparecerão quando o usuário abrir a caixa do componente (clicando na seta) é 84 Linguagens de Programação II.indb 84 7/12/2006 14:00:39 Linguagens de Programação II configurado através do método setMaximumRowCount(13). Nesse caso, o nome das treze primeiras cores aparecerá. Se houver itens adicionais, uma barra de rolagem é exibida junto com o componente. Linhas 17 e 18 – cria o objeto ouvinte de evento para esse tipo de evento – ItemEvent – e registra-se ele junto ao componente. Linha 20 – um componente JFrame ou frame consiste de três camadas: fundo, painel de conteúdo e o painel transparente. A camada painel de conteúdo aparece na frente da camada de fundo e é onde os componentes GUI são exibidos. A camada painel transparente é utilizada para exibir dicas dos componentes e outros itens que devem aparecer na frente dos componentes GUI. O painel de conteúdo oculta o fundo do frame. Portanto, para mudar a cor de fundo por trás dos componentes GUI, você deve mudar a cor do painel de conteúdo. O método getContentPane() retorna uma referência ao painel de conteúdo do JFrame. A partir dessa referência, é chamado o método setBackground() para configurar a cor do painel de conteúdo. É passada, como argumento, a referência do primeiro objeto Color armazenado no array cores na posição [0], nesse caso, Color.black. Linha 23 a 27 – início da classe interna que tratará o evento TratadorComboBox. Essa classe deve implementar a interface ItemListener porque o evento gerado pelo componente JComboBox é do tipo ItemEvent. Logo, o método a ser implementado é o itemStateChanged(). Dentro do método, é programado para que a cor de fundo do painel de conteúdo seja alterada para a cor correspondente ao item que o usuário escolheu no JComboBox. Cada item no componente é numerado de 0 ao número de itens armazenados no JComboBox - 1. O método listadecores.getSelectedIndex() retorna o índice (número) do item selecionado. Por exemplo, se você selecionou a cor “Ciano”, o índice retornado será 2 porque essa cor e o seu correspondente objeto Color foram inseridos no JComboBox na terceira posição (linha) . Com esse índice, é possível chamar o método Unidade 3 Linguagens de Programação II.indb 85 85 7/12/2006 14:00:39 Universidade do Sul de Santa Catarina setBackground() e passar, como argumento, o objeto Color que está no array cores na posição (índice) retornado pelo método getSelectedIndex(). Veja, abaixo, o código da classe TesteJComboBox. import javax.swing.JFrame; public class TesteJComboBox{ public static void main(String arg[]){ GuiJComboBox guijcombobox = new GuiJComboBox(); guijcombobox.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guijcombobox.setSize(275,280); guijcombobox.setVisible(true); } } 3.1 – Outros métodos de JComboBox A classe JComboBox possui outros métodos interessantes que podem ser usados no desenvolvimento de umaGUI: void addItem(Object anObject) – adiciona um item à lista do combo. Object getItemAt(int index) – retorna o item pelo seu índice. int getItemCount() – retorna o número de itens. Object getSelectedItem() – retorna o item selecionado. int getSelectedIndex() – retorna o índice do item selecionado. void insertItemAt(Object anObject, int index) – insere um item em uma posição específica. void removeItem(Object anObject) – remove o item especificado. 86 Linguagens de Programação II.indb 86 7/12/2006 14:00:39 Linguagens de Programação II Seção 4 – Componente JList O componente JList ou componente de lista permite que uma série de itens sejam exibidos numa caixa. O usuário pode escolher um ou mais itens dessa lista. JList permite a lista de seleção única, onde apenas um item pode ser escolhido, ou a lista de seleção múltipla, onde vários itens podem ser escolhidos. A manipulação do componente JList gera objeto de evento do tipo ListSelectionEvent que deve ser tratado por um objeto que implementa a interface ListSelectionListener. Saiba mais sobre o componente JList! Consulte a documentação referente a este componente em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JList.html A figura 3.4 mostra a GUI de uma aplicação onde vários nomes de pessoas são exibidos numa lista. Ao escolher um item da lista, o mesmo aparece no componente campo de texto. JList FIGURA 3.4 – GUI DA APLICAÇÃO TESTEJLIST Unidade 3 Linguagens de Programação II.indb 87 87 7/12/2006 14:00:40 Universidade do Sul de Santa Catarina O código, abaixo, refere-se à classe GuiJList. 1 import java.awt.*; 2 import java.awt.event.*; 3 import javax.swing.*; 4 import javax.swing.event.ListSelectionListener; //interface que trata o evento do componente JList 5 import javax.swing.event.ListSelectionEvent; //classe do evento 6 import javax.swing.ListSelectionModel; //classe que especifica o modo de seleção da lista 7 8 public class GuiJList extends JFrame{ 9 private JList nomeList; 10 private String nomes[]={“Andrea”,”Cristina”,”Joao”,”Lucas”}; 11 private JTextField nomeTextField; 12 13 public GuiJList() { 14 super(“Exemplo JList”); 15 setLayout(new FlowLayout()); 16 17 nomeList = new JList(nomes); 18 nomeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 19 nomeList.setSelectedIndex(0); 20 nomeList.setVisibleRowCount(3); 21 JScrollPane listScrollPane = new JScrollPane(nomeList); 22 add(listScrollPane); 23 TrataEventoList trataeventolist = new TrataEventoList(); //objeto ouvinte de evento de JList 24 nomeList.addListSelectionListener(trataeventolist); 25 26 nomeTextField = new JTextField(10); 27 add(nomeTextField); 28 } 29 30 31 private class TrataEventoList implements ListSelectionListener { 32 33 public void valueChanged(ListSelectionEvent e) { 34 nomeTextField.setText(nomes[nomeList.getSelectedIndex()]); 35 } 36 } 37 } //fim da classe Entenda o código, conforme a explicação abaixo: Linha 10 – declaração e inicialização de um array de String com o nome de várias pessoas. Linha 17 – criação do componente JList. No construtor do componente, o array de String com o nome das pessoas é passado como argumento. Isso faz com que os nomes sejam exibidos no componente. 88 Linguagens de Programação II.indb 88 7/12/2006 14:00:40 Linguagens de Programação II Linha 18 – o método setSelectionMode(ListSelectionModel. SINGLE_SELECTION) configura o modo de seleção da lista, um item ou vários itens. Nesse caso, é passado, como argumento, o valor constante ListSelectionModel.SINGLE_SELECTION, que faz com que apenas um item possa ser selecionado. As constantes que representam os modos de seleção estão na classe ListSelectionModel, importada na linha 6. As outras constantes são: SINGLE_INTERVAL_SELECTION, que permite a seleção de vários itens num único intervalo de seleção e MULTIPLE_ INTERVAL_SELECTION, que permite a seleção de vários itens. Linha 19 – o método setSelectedIndex(0) permite configurar qual o elemento que aparecerá selecionado inicialmente. É passado como argumento o índice do item na lista. Lembre-se que o primeiro item começa na posição, índice 0. Nesse caso, o primeiro item da lista aparecerá selecionado. Linha 20 – o método setVisibleRowCount(3) determina o número de itens que aparecerão visíveis na lista. Nesse caso, três itens aparecerão. Linha 21 – O componente JList não exibe automaticamente as barras de rolagem quando o número de itens for maior que o tamanho configurado para as linhas visíveis. É necessário criar um objeto do tipo JScrollPane para exibir essa funcionalidade. Como argumento para o construtor desse objeto, é passada a referência do componente JList criado na linha 17. Linha 22 – o componente JScrollPane é adicionado ao frame. Note que não é o próprio componente JList que é adicionado e, sim, o JScrollPane. Linha 23 e 24 – criação do objeto ouvinte de evento para o componente JList. Como você leu anteriormente, esse componente gera eventos do tipo ListSelectionEvent. Logo o objeto ouvinte de evento deve ser do tipo ListSelectionListener, que é a interface responsável por tratar esse tipo de evento. A classe TrataEventoList é criada na linha 31. Logo após, o objeto é registrado junto ao componente JList nomeList. Linha 26 e 27 – criação do componente JTextField. Adição dele ao container. Unidade 3 Linguagens de Programação II.indb 89 89 7/12/2006 14:00:40 Universidade do Sul de Santa Catarina Linha 31 a 36 – criação da classe interna que tratará o evento gerado pelo componente JList. Note que a classe TrataEventoList implementa a interface ListSelectionListener. Essa interface tem um único método abstract valueChanged (). Esse método será invocado sempre que um ou mais itens forem selecionados dentro do componente JList. Nesse caso, cada vez que um item for selecionado, quer-se que ele apareça no componente JTextField. Para isso, o método setText(nomes[nomeList.getSelectedIndex()]) do componente JTextField é invocado. É passado, como argumento, o conteúdo do array nomes[] na mesma posição do item selecionado. O método getSelectedIndex() do componente JList nomeList retorna à posição ou índice do item escolhido. Essa é mesma posição do item no array nomes[]. Veja o código da classe TesteJList. 1 import javax.swing.JFrame; 2 public class TesteJComboBox{ 3 4 public static void main(String[] args) { 5 GuiJList guijlist = new GuiJList(); 6 7 guijlist.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 8 guijlist.setSize(275,280); 9 guijlist.setVisible(true); 10 11 } 12 } Vamos criar outra aplicação que permita a seleção de múltiplos itens. Nessa aplicação, você poderá escolher vários itens na lista e depois clicar no botão “Copiar >>”, para copiar os itens selecionados para a outra lista. A figura 3.5 exibe a GUI dessa aplicação. FIGURA 3.5 – GUI DA APLICAÇÃO TESTEJLISTMULTIPLO 90 Linguagens de Programação II.indb 90 7/12/2006 14:00:40 Linguagens de Programação II O código desta outra aplicação é exibido abaixo: import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class GuiJListMultiplo extends JFrame{ private JList nomeList; private JList selecList; private String nomes[]={“Andrea”,”Cristina”,”Joao”,”Lucas”}; private JButton copiaButton; public GuiJListMultiplo() { super(“Exemplo JList com Multipla Seleção”); setLayout(new FlowLayout()); nomeList = new JList(nomes); nomeList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); nomeList.setSelectedIndex(0); nomeList.setVisibleRowCount(3); add(new JScrollPane(nomeList)); //cria o objeto JScrollPane dentro do metodo add que adiciona o JScrollPane ao frame copiaButton = new JButton(“Copia >>”); TrataEventoBotao trataeventobotao = new TrataEventoBotao(); copiaButton.addActionListener(trataeventobotao); add(copiaButton); selecList = new JList(); //lista vazia para armazenar os itens selecionados Linha 20 selecList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); selecList.setVisibleRowCount(3); selecList.setFixedCellWidth(100); //configura a largura da lista selecList.setFixedCellHeight(15); //configura a altura da lista add(new JScrollPane(selecList)); } Linha 35 private class TrataEventoBotao implements ActionListener { public void actionPerformed(ActionEvent e) { Linha 37 selecList.setListData(nomeList.getSelectedValues()); } } } Observe, agora, a explicação de alguns trechos do código: Linha 20 – nessa linha, é configurado o modo de seleção de itens da lista para múltiplas seleções. Unidade 3 Linguagens de Programação II.indb 91 91 7/12/2006 14:00:41 Universidade do Sul de Santa Catarina Linha 35 – a cópia dos itens selecionados deve ocorrer quando o usuário clicar no botão “Copiar”. Portanto, é o evento gerado pelo componente JButton que deve ser tratado. Nessa aplicação, não queremos que algo aconteça quando o usuário selecionar itens no componente JList e, sim, quando o usuário clicar no botão. Portanto, devemos saber qual o tipo de evento gerado pelo componente JButton. Esse componente já foi trabalhado na unidade 2, ele gera eventos do tipo ActionEvent e deve ser tratado por um objeto ouvinte de evento do tipo ActionListener. Por isso, a classe que inicia nessa linha implementa a interface ActionListener. Se a classe implementa essa interface, então ela deve redefinir o método actionPerformed() e, dentro dele, deve ser programado para que os itens selecionados na primeira lista sejam copiados para a segunda lista. Linha 37 – o método setListData() configura no componente JList selecList os itens que serão exibidos nele. É passado, como argumento, o conjunto de itens selecionados no componente JList nomeList. O método getSelectedValues() retorna o conjunto de itens selecionados em JList nomeList. 92 Linguagens de Programação II.indb 92 7/12/2006 14:00:41 Linguagens de Programação II 4.1 – Outros métodos de JList A classe JList possui outros métodos interessantes que podem ser usados no desenvolvimento de uma GUI: void clearSelection() – limpa a marca de seleção. int getMinSelectionIndex() e int getMaxSelectionIndex() – retorna o índice mínimo e índice máximo em uma seleção. int getSelectedIndex() e int[] getSelectedIndices() – retorna o índice dos itens selecionados. Object getSelectedValue() e Object[] getSelectedValues() – retorna os itens selecionados. boolean isSelectionEmpty() – retorna true, se não houver nada selecionado. void setListData(Object[] listData) – constrói a lista com os valores do parâmetro. Síntese Nesta unidade, você conheceu mais alguns componentes Swing e trabalhou com outros tipos de eventos. O assunto GUI e tratamento de eventos têm um certo nível de dificuldade, portanto, nossa intenção foi que você conhecesse mais alguns componentes e seus eventos, de maneira didática e simplificada. Você observou que cada componente possui um conjunto de métodos adicionais que foram exibidos no final de cada seção. Explore um pouco mais esses métodos, propondo variações nas aplicações apresentadas até aqui ou criando novas aplicações. Considere como modelos os exercícios trabalhados nas disciplinas de programação anteriores. Unidade 3 Linguagens de Programação II.indb 93 93 7/12/2006 14:00:41 Universidade do Sul de Santa Catarina Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Desenvolva uma aplicação com a seguinte GUI. Nessa aplicação, o usuário deve entrar com o total bruto da compra e escolher a forma de pagamento (à vista ou a prazo). Se for escolhida a forma de pagamento à vista, o usuário deve digitar o desconto (%) no outro componente que vai aparecer somente nesse caso, conforme a GUI abaixo mostra. 94 Linguagens de Programação II.indb 94 7/12/2006 14:00:41 Linguagens de Programação II Depois de digitar o desconto, o usuário apertará a tecla Enter nesse componente e o valor líquido aparecerá, calculado no campo total líquido. Caso seja escolhida a forma de pagamento a prazo, o componente de entrada do desconto não deve aparecer e o valor da compra deve ser mostrado no campo total líquido. Dicas: 1) Para tornar visível ou não visível os componentes JLabel e JTextField use o método setVisibel(). Passe o argumento true para deixar visível o componente e false para ocultar. 2) Nessa GUI, dois tipos de eventos devem ser tratados. ItemEvent, que é disparado quando o usuário interage com o componente JRadioButton, e (preste atenção!) ActionEvent, quando o usuário interage com o componente JTextField, apertando a tecla Enter quando o foco está no componente. Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando a seguinte referência, principalmente os capítulos 10, 11 e 12: DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. Consulte, também, os seguintes sites: http://www.csie.ntu.edu.tw/~piaip/docs/Swing/ (Swing The Book) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter9html/ (ComboBox) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter10html/ (List) http://java.sun.com/docs/books/tutorial/uiswing/components/button. html (How to Use Buttons, CheckBoxes and Radiop Buttons) Unidade 3 Linguagens de Programação II.indb 95 95 7/12/2006 14:00:42 Linguagens de Programação II.indb 96 7/12/2006 14:00:42 UNIDADE 4 Trabalhando com Layout de Componentes 4 Objetivos de aprendizagem Conhecer o componente JTextArea. Conhecer outra forma de tratar eventos. Conhecer outros gerenciadores de layout. Construir GUI com layout mais complexo. Seções de estudo Seção 1 Componente JTextArea Seção 2 Utilização de Classe Interna Anônima para Tratar Eventos Seção 3 Gerenciadores de Layout Seção 4 Construindo uma GUI com Layout mais Complexo Linguagens de Programação II.indb 97 7/12/2006 14:00:42 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você conhecerá mais um componente Swing, conhecido como área de texto. Aprenderá a tratar eventos de uma outra forma, ainda através de uma classe interna, mas dessa vez anônima, ou seja, você não precisará declarar o cabeçalho da classe da forma como foi feito nas unidades anteriores. As duas últimas seções abordarão o assunto do título dessa unidade, layout. Você terá contato com outros tipos de Gerenciadores de Layout, além do utilizado até o momento que foi o FlowLayout. Além disso, começará a construir GUI´s com layout mais complexos. Seção 1 – Componente JTextArea O componente JTextArea fornece uma área para manipular texto. Esse componente não gera eventos, assim como o componente JList de múltipla seleção. Nesse caso, é preciso existir outro componente que gere evento para se executar a ação desejada. A figura 4.1 mostra uma aplicação onde um texto inicial é exibido em um dos componentes JTextArea. Veja que o usuário deve selecionar uma parte do texto e clicar no botão “Copiar”. O texto selecionado é copiado para o segundo componente JTextoArea. FIGURA 4.1 – GUI DA APLICAÇÃO TESTEJTEXTAREA 98 Linguagens de Programação II.indb 98 7/12/2006 14:00:42 Linguagens de Programação II O código da aplicação, referente ao componente JTextArea, é exibido abaixo: 1 import java.awt.FlowLayout; 2 import java.awt.event.ActionListener; 3 import java.awt.event.ActionEvent; 4 import javax.swing.JFrame; 5 import javax.swing.JTextArea; 6 import javax.swing.JButton; 7 import javax.swing.JScrollPane; 8 9 public class GuiJTextArea extends JFrame 10 { 11 private JTextArea textArea1; // exibe o texto original 12 private JTextArea textArea2; // exibe o texto destacado 13 private JButton copiaButton; // copia o texto 14 15 16 public GuiJTextArea() { 17 super( “Exemplo JTextArea” ); 18 setLayout(new FlowLayout()); 19 20 String textOriginal = “Desenvolver habilidades que propiciem ao \n”+ 21 “educando a capacidade de criar, programar e implantar sistemas \n”+ 22 “computacionais em ambientes WEB, com embasamento teórico e sólida formação prática.”; 23 24 25 textArea1 = new JTextArea( textOriginal, 15, 25 ); // cria textarea1, configura linhas e colunas 26 add(new JScrollPane( textArea1 )); // adiciona scrollpane ao frame 27 copiaButton = new JButton( “Copiar >>>” ); // cria botão de cópia 28 copiaButton.addActionListener(new TrataEventoBotao()); 29 add( copiaButton ); // adiciona o botão de cópia ao frame 30 31 textArea2 = new JTextArea( 15, 25 ); // cria segundo textarea 32 textArea2.setEditable( false ); // desativa a edição 33 add( new JScrollPane( textArea2 ) ); // adiciona scrollpane ao frame 34 } // fim do construtor 35 36 37 private class TrataEventoBotao implements ActionListener { 38 public void actionPerformed(ActionEvent e) { 39 textArea2.setText( textArea1.getSelectedText() ); 40 } 41 } 42 } // fim da classe Confira agora a explicação desse código: Linhas 25 e 31 – criam os dois componentes JTextArea. Na linha 25, é passada, como argumento para o construtor, a String contendo o texto original (declarada e inicializada na linha 20), o número de linhas e colunas exibidas pelo componente. Unidade 4 Linguagens de Programação II.indb 99 99 7/12/2006 14:00:42 Universidade do Sul de Santa Catarina Linha 26 – cria um componente JScrollPane e o adiciona ao frame, com o método add(). Lembre-se que esse componente exibe as barras de rolagem, nesse caso, no componente JTextArea. Para o construtor de JScrollPane é passado o componente onde as barras deverão ser exibidas, nesse caso, JTextArea textArea1. Linhas 27 a 29 – criam o componente JButton copiaButton. Adiciona-se o objeto ouvinte de evento ao objeto JButton. Adiciona-se o componente JButton ao frame. Note que trataremos o evento gerado por esse componente, por isso, adicionamos a ele um objeto ouvinte de evento do tipo ActionListener. O objeto ouvinte de evento é do tipo ActionListener e, por isso, a classe TrataEventoBotao, da linha 37, implementa a interface ActionListener. Linhas 31 a 33 – cria o segundo componente JTextArea. Configura-se o componente para que não possa ser editado com o método setEditable (false). Cria-se um JScrollPane que adiciona o componente JTextArea a ele (para exibição das barras de rolagem). Adiciona-se o JScrollPane ao frame. Linha 39 – o componente JTextArea textArea2 é configurado para armazenar e exibir o texto selecionado no componente JTextArea textArea1. O método setText() armazena algum texto no componente JTextArea. O método getSelectedText() retorna o texto selecionado no componente JTextArea. O código abaixo refere-se à aplicação TesteJTextArea: import javax.swing.JFrame; public class TesteJTextArea { public static void main( String args[] ) { GuiJTextArea guitextarea = new GuiJTextArea(); guitextarea.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); guitextarea.setSize( 725, 300 ); guitextarea.setVisible( true ); } } 100 Linguagens de Programação II.indb 100 7/12/2006 14:00:43 Linguagens de Programação II Seção 2 – Utilização de Classe Interna Anônima para Tratar Eventos Uma classe interna anônima é um outro tipo de classe interna que é declarada sem nome, por isso chamada de anônima. Normalmente, ela é declarada dentro de um método da classe, diferente da forma como apresentamos até aqui, declarada dentro da classe. Como as outras classes internas, uma classe interna anônima pode acessar os membros da sua classe de primeiro nível. Porém, ela só pode acessar as variáveis locais com o modificador final do método em que for declarada. Variáveis locais que tiverem modificador final não podem ser acessadas. Acompanhe a demonstração e utilização de uma classe interna anônima para tratar o mesmo evento da aplicação anterior. 1 import java.awt.FlowLayout; 2 import java.awt.event.ActionListener; 3 import java.awt.event.ActionEvent; 4 import javax.swing.JFrame; 5 import javax.swing.JTextArea; 6 import javax.swing.JButton; 7 import javax.swing.JScrollPane; 8 9 public class GuiJTextArea extends JFrame 10 { 11 private JTextArea textArea1; // exibe o texto original 12 private JTextArea textArea2; // exibe o texto destacado 13 private JButton copiaButton; // copia o texto 14 15 16 public GuiJTextArea() { 17 super( “Exemplo JTextArea” ); 18 setLayout(new FlowLayout()); 19 20 String textOriginal = “Desenvolver habilidades que propiciem ao \n”+ 21 “educando a capacidade de criar, programar e implantar sistemas \n”+ 22 “computacionais em ambientes WEB, com embasamento teórico e sólida formação prática.”; 23 24 25 textArea1 = new JTextArea( textOriginal, 15, 25 ); // cria textarea1, configura linhas e colunas 26 add(new JScrollPane( textArea1 )); // adiciona scrollpane ao frame 27 28 29 30 31 copiaButton = new JButton( “Copiar >>>” ); // cria botão de cópia add(copiaButton); ActionListener ouvinte = new ActionListener(){ public void actionPerformed(ActionEvent e) { textArea2.setText( textArea1.getSelectedText() ); Unidade 4 Linguagens de Programação II.indb 101 101 7/12/2006 14:00:43 Universidade do Sul de Santa Catarina 32 33 34 } }; copiaButton.addActionListener(ouvinte); 35 36 textArea2 = new JTextArea( 15, 25 ); // cria segundo textarea 37 textArea2.setEditable( false ); // desativa a edição 38 add( new JScrollPane( textArea2 ) ); // adiciona scrollpane ao frame 39 } // fim do construtor 40 } // fim da classe Note que a classe interna que existia na versão anterior não existe mais. Agora, ela, a classe interna, tornou-se anônima e está declarada nas linhas 28 a 32. Ela inicia no símbolo de { da linha 28 e termina no símbolo de } da linha 32. Já que a classe interna anônima não tem nome, deve-se criar um objeto da classe interna anônima no ponto em que ela é declarada. Isso está acontecendo no início da linha 28: ActionListener ouvinte = new ActionListener(). É criado um objeto ouvinte de evento do tipo ActionListener. Na linha 33, esse objeto ouvinte de evento é registrado junto ao componente JButton copiaButton para tratar o evento ActionEvent gerado por ele. Uma forma mais direta de trabalhar com classe interna anônima nessa aplicação segue abaixo: copiaButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { textArea2.setText( textArea1.getSelectedText() ); } }); O objeto do tipo ActionListener é criado dentro do método addActionListener(), que adiciona o objeto ao componente JButton. A classe interna anônima começa no primeiro { e termina no último }. 102 Linguagens de Programação II.indb 102 7/12/2006 14:00:43 Linguagens de Programação II Seção 3 – Gerenciadores de Layout Os gerenciadores de layout são utilizados para organizar os componentes GUI em um container. Os componentes GUI também podem ser organizados no container sem o uso de um gerenciador de layout. Mas, nesse caso, o programador deve se preocupar com a posição absoluta do componente em relação ao container e também com o tamanho de cada componente. Isso pode ser extremamente trabalhoso! Ao usar um gerenciador de layout você ganha rapidez para criar GUI´s , mas pode perder algum controle sobre o tamanho e a posição exata de cada componente inserido da GUI. Existe uma outra forma muito fácil e agradável de programar GUI. Use uma IDE (ambiente de desenvolvimento integrado) com recursos para desenhar GUI. Com esse tipo de ferramenta, você simplesmente escolhe o componente GUI numa barra de componentes, arrasta e solta o componente na posição que você quer da janela. Quem produz o código para você é a própria ferramenta. Além disso, você pode programar o código para o tratamento do evento gerado por um componente, clicando duas vezes em cima do componente inserido na janela. Este procedimento abrirá o código fonte no ponto necessário para você só inserir o código do processamento do evento, ou seja, você não se preocupa em criar a classe que implementa a interface que trata o evento, etc. Observe que esse recurso não é utilizado nesses capítulos sobre GUI, porque nosso objetivo é que você aprenda como fazer tais códigos do “zero”. Veja, agora, vários gerenciadores de layout. Com eles, você poderá construir GUI´s mais complexas, ou seja, com vários componentes inseridos e alinhados, da maneira que você deseja. Unidade 4 Linguagens de Programação II.indb 103 103 7/12/2006 14:00:43 Universidade do Sul de Santa Catarina 3.1 – FlowLayout Esse gerenciador já é conhecido por você. É o gerenciador mais simples de ser utilizado. Com ele, os componentes são inseridos no container da esquerda para a direita e na ordem que você os adicionou no código-fonte. Quando algum componente alcança a borda do container, os demais são inseridos na próxima linha. Esse gerenciador permite que os componentes sejam alinhados à esquerda, centralizados ou alinhados à direita, prevalecendo as características descritas anteriormente. Se nenhum tipo de alinhamento for estabelecido, como foi o caso das nossas aplicações até agora, os componentes são centralizados. Esse gerenciador também respeita o tamanho dos componentes gerenciados por ele. Veja que a aplicação, a seguir, mostra o uso do gerenciador FlowLayout de uma maneira um pouco diferente da usada até o momento. Nessa aplicação, são exibidos apenas três botões, dispostos através do FlowLayout, inicialmente alinhados à esquerda. A figura 4.2 ilustra a GUI. FIGURA 4.2 – GUI DA APLICAÇÃO GUIFLOWLAYOUT Vamos analisar o código da aplicação. 1 import java.awt.FlowLayout; 2 import javax.swing.JFrame; 3 import javax.swing.JButton; 4 5 public class GuiFlowLayout extends JFrame 6 { 7 private JButton leftJButton; // botão para configurar alinhamento à esquerda 8 private JButton centerJButton; // botão para configurar alinhamento centralizado 9 private JButton rightJButton; // botão para configurar alinhamento à direita 10 private FlowLayout layout; // objeto de layout 11 12 public GuiFlowLayout() 13 { 104 Linguagens de Programação II.indb 104 7/12/2006 14:00:43 Linguagens de Programação II 14 super( “Teste com o Gerenciador de Layout FlowLayout” ); 15 16 layout = new FlowLayout(); // cria objeto FlowLayout 17 layout.setAlignment(FlowLayout.LEFT); // configura o alinhamento do frame 18 setLayout( layout ); // configura o layout de frame 19 20 // configura leftJButton 21 leftJButton = new JButton( “Esquerdo” ); // cria botão Esquerdo 22 add( leftJButton ); // adiciona o botão Esquerdoao frame 23 24 // configura centerJButton 25 centerJButton = new JButton( “Centro” ); // cria botão Centro 26 add( centerJButton ); // adiciona botão Centroao frame 27 28 // configura rightJButton 29 rightJButton = new JButton( “Direito” ); // cria botão Direito 30 add( rightJButton ); // adiciona botão Direitoao frame 31 32 } // fim do construtor FlowLayoutFrame 33 34 public static void main(String args[]){ 35 GuiFlowLayout guiflowlayout = new GuiFlowLayout(); 36 guiflowlayout.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 37 guiflowlayout.setSize(475,80); 38 guiflowlayout.setVisible(true; 39 } 40} // fim da classe Linha 17 – confira o alinhamento dos componentes dentro do layout através do método setAlignment(). Podem ser passadas, como argumento, as seguintes constantes: FlowLayout.LEFT, FlowLayout.CENTER ou FlowLayout.RIGHT. Linha 34 – observe que nessa classe temos o construtor na linha 12 e o método main() na linha 34. Essa é a primeira vez que o método main() aparece dentro da classe que cria a GUI. Essa configuração é perfeitamente possível. Toda classe que possui método main() é executável. O que está programado dentro do método? A criação de um objeto do tipo GuiFlowLayout na linha 35. Esse objeto chama o construtor da classe, que, por sua vez, monta a GUI. Unidade 4 Linguagens de Programação II.indb 105 105 7/12/2006 14:00:44 Universidade do Sul de Santa Catarina 3.2 – BorderLayout O gerenciador BorderLayout é o gerenciador padrão de um JFrame. Assim, quando nenhum gerenciador for especificado, ele é utilizado. Esse gerenciador organiza os componentes GUI em cinco (5) regiões na tela: NORTH (norte), SOUTH (sul), EAST (leste), WEST (oeste) e CENTER (centro). Com esse gerenciador, você pode inserir apenas cinco componentes no container, um em cada região. Não ache estranho, pois podemos inserir, nessas regiões, componentes (containers) como JPanel, que permitem que outros componentes GUI sejam adicionados a eles, construindo, com isso, GUIs mais complexas. Você estudará este caso na próxima seção. Os componentes inseridos nas regiões NORTH e SOUTH estendem-se horizontalmente para os lados do container e têm a altura do componente mais alto inserido nessas regiões. Os componentes inseridos nas regiões EAST e WEST estendem-se verticalmente entre as regiões NORTH e SOUTH e têm a mesma largura que os componentes colocados nas suas regiões. O componente inserido na região CENTER expande-se para ocupar todo o espaço restante do layout. Se todas as regiões estão ocupadas, todo o espaço do container é preenchido. Se as regiões NORTH e SOUTH não estão ocupadas, os componentes das regiões EAST, WEST e CENTER estendem-se para ocupar essas duas regiões. Se as regiões EAST e WEST não estão ocupadas, o componente da região CENTER ocupa o espaço dessas duas regiões. Se a região CENTER não é ocupada, esta área fica vazia, ou seja, os componentes das outras regiões não ocupam esse espaço. Os componentes dispostos nesse tipo de gerenciador geralmente não conseguem ter seu tamanho preferido. A figura 4.3 exibe a GUI de uma aplicação onde foram inseridos cinco componentes JButton, um em cada região do container. Ao clicar em algum botão, ele se torna invisível e os outros componentes ocupam o seu espaço. Note que isso não vai acontecer com o componente JButton da região CENTER. 106 Linguagens de Programação II.indb 106 7/12/2006 14:00:44 Linguagens de Programação II FIGURA 4.3 – GUI DA APLICAÇÃO GUIBORDERLAYOUT Observe a análise do código da aplicação GuiBorderLayout: 1 import java.awt.BorderLayout; 2 import java.awt.event.ActionListener; 3 import java.awt.event.ActionEvent; 4 import javax.swing.JFrame; 5 import javax.swing.JButton; 6 7 public class GuiBorderLayout extends JFrame 8{ 9 private JButton button1; // 10 private JButton button2; // 11 private JButton button3; // 12 private JButton button4; // 13 private JButton button5; // 15 private BorderLayout layout; // objeto borderlayout 16 17 // configura GUI e tratamento de evento 18 public GuiBorderLayout() 19 { 20 super( “Exemplo com Gerenciador BorderLayout” ); 21 22 layout = new BorderLayout( 5, 5 ); // cria o gerenciador com espaços de 5 pixels 23 setLayout( layout ); // configura o layout do frame para BorderLayout 24 25 button1 = new JButton(“Norte”); 26 add( button1, BorderLayout.NORTH );// adiciona botão para o norte 27 28 TrataEventoBotao tratabotao = new TrataEventoBotao(); 29 button1.addActionListener(tratabotao); 30 31 button2 = new JButton(“Sul”); 32 add( button2, BorderLayout.SOUTH ); // adiciona botão para o sul 33 button2.addActionListener(tratabotao); 34 35 button3 = new JButton(“Leste”); 36 add( button3, BorderLayout.EAST );// adiciona botão para o leste 37 button3.addActionListener(tratabotao); 38 39 button4 = new JButton(“Oeste”); 40 add( button4, BorderLayout.WEST );// adiciona botão para o oeste 41 button4.addActionListener(tratabotao); 42 Unidade 4 Linguagens de Programação II.indb 107 107 7/12/2006 14:00:44 Universidade do Sul de Santa Catarina 43 button5 = new JButton(“Centro”); 44 add( button5, BorderLayout.CENTER );// adiciona botão para o centro 45 button5.addActionListener(tratabotao); 46 47 } // fim do construtor GuiBorderLayout 48 49 private class TrataEventoBotao implements ActionListener{ 50 // trata os eventos de botão 51 public void actionPerformed( ActionEvent event ) { 52 if (event.getSource() == button1){ 53 button1.setVisible( false ); // oculta o botão clicado 54 button2.setVisible( true ); // exibe os demais 55 button3.setVisible( true ); 56 button4.setVisible( true ); 57 button5.setVisible( true ); 58 }else 59 if (event.getSource() == button2){ 60 button2.setVisible( false ); // oculta o botão clicado 61 button1.setVisible( true ); // exibe os demais 62 button3.setVisible( true ); 63 button4.setVisible( true ); 64 button5.setVisible( true ); 65 } else 66 if (event.getSource() == button3){ 67 button3.setVisible( false ); // oculta o botão clicado 68 button1.setVisible( true ); // exibe os demais 69 button2.setVisible( true ); 70 button4.setVisible( true ); 71 button5.setVisible( true ); 72 }else 73 if (event.getSource() == button4){ 74 button4.setVisible( false ); // oculta o botão clicado 75 button1.setVisible( true ); // exibe os demais 76 button2.setVisible( true ); 77 button3.setVisible( true ); 78 button5.setVisible( true ); 79 } else 80 if (event.getSource() == button5){ 81 button5.setVisible( false ); // oculta o botão clicado 82 button1.setVisible( true ); // exibe os demais 83 button2.setVisible( true ); 84 button3.setVisible( true ); 85 button4.setVisible( true ); 86 } 87 88 layout.layoutContainer( getContentPane() ); // painel de conteúdo de layout 89 90 } // fim do método actionPerformed() 91 } //fim da classe interna. Essa classe não é anônima 92 93 public static void main( String args[] ) { 94 GuiBorderLayout borderLayout = new GuiBorderLayout(); 95 borderLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 96 borderLayout.setSize( 300, 200 ); // configura o tamanho do frame 97 borderLayout.setVisible( true ); // exibe o frame 98 } // fim de main 99 100 } // fim da classe GuiBorderLayout 108 Linguagens de Programação II.indb 108 7/12/2006 14:00:44 Linguagens de Programação II Acompanhe a análise de algumas destas linhas. Linha 22 – criar o objeto gerenciador de layout BorderLayout. Para o construtor é passado, como argumento, o espaçamento horizontal entre os componentes e o espaçamento vertical entre os componentes. Esse valor é o número de pixels. Linhas 26, 32, 36, 40 e 44 – adicionam os cinco componentes JButton ao container e especificam a região onde cada componente será inserido. As regiões são representadas pelas constantes BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST, BorderLayout.WEST e BorderLayout. CENTER. Linha 28 – cria um objeto ouvinte de evento do tipo ActionListener. Esse objeto será registrado junto aos cinco componentes JButton (linhas 29, 33, 37, 41 e 45). É ele que tratará o evento ActionEvent gerado quando o usuário clicar em algum dos botões. Linha 49 – início da classe interna que tratará o evento gerado pelos botões. Essa classe implementa a interface ActionListener porque o evento gerado por um botão é do tipo ActionEvent. Linha 51 – início do método actionPerformed(). Dentro do método é verificado qual o componente que originou o evento. Se for o componente button1 é porque o componente inserido na região NORTH foi clicado, logo, ele será configurado para ficar invisível com o método setVisible(false) do componente JButton e os demais componentes serão configurados para ficarem visíveis com o método setVisible(true). Assim, os componentes do container devem ser reorganizados e os botões inseridos nas regiões EAST, CENTER e WEST ocuparão o espaço que antes era do botão da região NORTH. A figura 4.4 demonstra como ficará a GUI nessa situação. Unidade 4 Linguagens de Programação II.indb 109 109 7/12/2006 14:00:44 Universidade do Sul de Santa Catarina FIGURA 4.4 – GUI DA APLICAÇÃO GUIBORDERLAYOUT SEM BOTÃO NA REGIÃO NORTE Observe que esse teste é feito para todos os componentes JButton. No final do teste, na linha 88, o layout desse painel de conteúdo (lembre que os componentes GUI estão numa camada intermediária chamada de painel de conteúdo) deve ser reorganizado. Para isso o método layoutContainer() do objeto BorderLayout é chamado layout. O painel de conteúdo utilizado na GUI é passado para método como argumento. . Esse painel de conteúdo é obtido com o método getContentPane() que retorna o painel de conteúdo. Linha 93 – início do método main(). 3.3 – GridLayout O gerenciador GridLayout permite que vários componentes GUI sejam inseridos dentro de uma grade ou tabela. A dimensão da grade, ou o número de linhas e colunas, é feita no construtor do objeto gerenciador de layout. Nesse gerenciador, cada componente tem a mesma largura e altura. Os componentes são inseridos a partir da primeira célula da primeira linha. A figura 4.5 mostra a GUI de uma aplicação onde seis componentes JButton foram inseridos e organizados através do gerenciador GridLayout. Nessa aplicação, não foi programada qualquer ação para os componentes JButton. Ela objetiva apenas mostrar como funciona a disposição dos componentes segundo esse gerenciador de layout. 110 Linguagens de Programação II.indb 110 7/12/2006 14:00:44 Linguagens de Programação II FIGURA 4.5 – GUI DA APLICAÇÃO GUIGRIDLAYOUT O código da aplicação é mostrado abaixo: 1 import java.awt.GridLayout; 2 import java.awt.Container; //importação da classe Container 3 import java.awt.event.ActionListener; 4 import java.awt.event.ActionEvent; 5 import javax.swing.JFrame; 6 import javax.swing.JButton; 7 8 public class GuiGridLayout extends JFrame 9 { 10 private JButton buttons[]; // array de botões 11 private final String names[] = 12 { “Botão 1”, “Botão 2”, “Botão 3”, “Botão 4”, “Botão 5”, “Botão 6”}; //array nome dos botões 13 private Container container; // contêiner do frame 14 private GridLayout gridLayout; // primeiro gridlayout 15 16 // construtor sem argumento 17 public GuiGridLayout() { 18 super( “Exemplo com Gerenciador GridLayout” ); 19 gridLayout = new GridLayout( 2, 3, 5, 5 ); // 2 por 3; lacunas de 5 20 21 container = getContentPane(); // obtém painel de conteúdo 22 container.setLayout( gridLayout ); // configura o layout JFrame 23 buttons = new JButton[ names.length ]; // cria array de JButtons 24 25 for ( int count = 0; count < names.length; count++ ) 26 { 27 buttons[ count ] = new JButton( names[ count ] ); 28 container.add( buttons[ count ] ); // adiciona o botão ao JFrame 29 } // final do for 30 31 } // fim do construtor GuiGridLayout 32 33 public static void main( String args[] ) 34 { 35 GuiGridLayout gridLayout = new GuiGridLayout(); 36 gridLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 37 gridLayout.setSize( 300, 200 ); // configura o tamanho do frame 38 gridLayout.setVisible( true ); // exibe o frame 39 } // fim de main 40 41 } // fim da classe Unidade 4 Linguagens de Programação II.indb 111 111 7/12/2006 14:00:45 Universidade do Sul de Santa Catarina Linha 10 – ao invés de se criar seis variáveis do tipo JButton, é criado um array de objetos JButton. Linha 11 – array de String para armazenar o nome ( rótulo ) de cada botão. Linha 13 – criação de uma variável do tipo container. Essa classe representa o painel de conteúdo do frame. É a primeira vez que estamos usando a variável do tipo container. Em breve esta variável será explicada com mais detalhes. Linha 14 – criação da variável que armazenará a referência a um objeto do tipo GridLayout (gerenciador de layout). Linha 19 – criação do objeto gerenciador de layout. Para o construtor, é passado o número de linhas e de colunas da grid além do espaçamento horizontal e vertical em pixels, entre os componentes na grid. O espaçamento em pixel padrão é 1. Linha 21 – o método getContentPane() retorna a referência ao objeto painel de conteúdo usado no frame. Essa referência é armazenada na variável container. Linha 22 – o layout do container é configurado através do método setLayout(). Desta vez, o método está associado à variável container. Essa é outra forma de configurar o layout do painel de conteúdo (“menos direta”). É passado, como argumento, a variável layout que contém a referência ao gerenciador de layout desejado. Linha 23 – a criação do array buttons[] é finalizada nessa linha. Na linha 10, foi criada apenas a variável referência do array. Note que o tamanho desse array é o tamanho do array names[]. O tamanho de um array é obtido com o seu atributo length, portanto, names.length retorna o tamanho do array names[]. Esse será o tamanho do array buttons[]. Linhas 25 a 29 – é usado um for para criação os seis objetos JButton. A referência de cada objeto JButton é armazenada numa posição do array buttons[] (linha 27). Logo após, na linha 28, cada objeto JButton é adicionado ao container. Lembre que o gerenciador GridLayout adiciona cada componente na grade, a partir da primeira linha da esquerda para a direita. 112 Linguagens de Programação II.indb 112 7/12/2006 14:00:45 Linguagens de Programação II 3.4 – BoxLayout O gerenciador BoxLayout é como o gerenciador FlowLayout, pelo fato de que cada componente pode ter seu próprio tamanho e pelos componentes serem inseridos na ordem em que são adicionados ao container. Mas o gerenciador BoxLayout difere do FlowLayout porque permite empilhar os componentes horizontalmente e verticalmente (o gerenciador FlowLayout só permite empilhar os componentes horizontalmente). A figura 4.6 mostra a GUI de uma aplicação onde um par de componentes JLabel e JTextField são inseridos na seqüência. Veja que a aplicação não trata nenhum evento. FIGURA 4.6 – GUI DA APLICAÇÃO GUIBOXLAYOUT Acompanhe a análise do código da aplicação, referente ao gerenciador BoxLayout: 1 import javax.swing.BoxLayout; 2 import javax.swing.JFrame; 3 import javax.swing.JLabel; 4 import javax.swing.JTextField; 5 6 public class GuiBoxLayout extends JFrame 7{ 8 private JLabel labelNome; 9 private JLabel labelEndereco; 10 private JLabel labelCidade; 11 private JTextField textfieldNome; 12 private JTextField textfieldEndereco; 13 private JTextField textfieldCidade; 14 15 private BoxLayout boxLayout; // primeiro gridlayout 16 17 18 // construtor sem argumento Unidade 4 Linguagens de Programação II.indb 113 113 7/12/2006 14:00:45 Universidade do Sul de Santa Catarina 19 public GuiBoxLayout() 20 { 21 super( “Exemplo com Gerenciador BoxLayout” ); 22 boxLayout = new BoxLayout(getContentPane(), BoxLayout.Y_AXIS ); // verticalmente 23 24 setLayout( boxLayout ); // configura o layout JFrame 25 26 labelNome = new JLabel(“Nome”); 27 add(labelNome); 28 29 textfieldNome = new JTextField(30); 30 add(textfieldNome); 31 labelEndereco = new JLabel(“Endereço”); 32 add(labelEndereco); 33 34 textfieldEndereco = new JTextField(30); 35 add(textfieldEndereco); 36 37 labelCidade = new JLabel(“Cidade”); 38 add(labelCidade); 39 40 textfieldCidade = new JTextField(30); 41 add(textfieldCidade); 42 43 } // fim do construtor GuiGridLayout 44 45 public static void main( String args[] ) 46 { 47 GuiBoxLayout boxLayout = new GuiBoxLayout(); 48 boxLayout.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 49 boxLayout.setSize( 300, 200 ); // configura o tamanho do frame 50 boxLayout.setVisible( true ); // exibe o frame 51 } // fim do main 52 53} // fim da classe Veja agora a análise da linha 22. Linha 22 – cria-se o gerenciador de layout BoxLayout. Como argumento para o construtor, é passado o painel de conteúdo, obtido com o método getContenPane(), e o alinhamento desejado vertical (BoxLayout.Y.AXIS) ou horizontal (BoxLayout.X.AXIS). Nesse caso, está sendo passado o alinhamento vertical. Para usar esse gerenciador é necessário informar o painel de conteúdo que ele será aplicado. 114 Linguagens de Programação II.indb 114 7/12/2006 14:00:45 Linguagens de Programação II Seção 4 – Construindo uma GUI com Layout mais complexo Para construir GUI com layout mais elaborado, você precisará trabalhar com múltiplos painéis. Até agora, trabalhamos com um painel, o painel de conteúdo padrão do JFrame. Para criar outro painel é necessário usar a classe JPanel. Um JPanel, conhecido como painel ou panel, também é considerado um componente GUI, e isso quer dizer que um JPanel pode tratar eventos como uso do mouse, pressionamento de teclas, etc. JPanel é um componente do tipo container e, em função disso, é possível adicionar outros componentes GUI a ele. Você já deve ter percebido que uma GUI mais elaborada será composta de vários componentes JPanel, onde cada um terá mais componentes GUI associados a ele, inclusive outros JPanel, e cada um poderá ser gerenciado por um gerenciador de layout específico. O gerenciador de layout controla os componentes que se encontram dentro do componente ao qual ele está associado. Se um JFrame contiver um JPanel e este contiver um JButton, então o gerenciador de layout do painel controlará o tamanho e a inserção do botão, enquanto que o gerenciador de layout do frame controlará o tamanho e a inserção do painel. FlowLayout é o gerenciador de layout padrão de um JPanel. A figura 4.7 mostra uma GUI onde quatro botões aparecem na região sul do frame. Para construir essa GUI, foi necessário, primeiramente, criar um JPanel, configurar o layout desse JPanel para GridLayout de uma (1) linha e quatro colunas e adicionar os quatro botões a ele. Posteriormente, o JPanel foi adicionado ao frame na região SOUTH do container. Lembre que o gerenciador de layout padrão de todo JFrame é BorderLayout. Num gerenciador BorderLayout é necessário especificar a região onde o componente será inserido. Unidade 4 Linguagens de Programação II.indb 115 115 7/12/2006 14:00:45 Universidade do Sul de Santa Catarina FIGURA 4.7 – GUI DA APLICAÇÃO GUIJPANEL O código, referente ao componente JPanel, é exibido a seguir: 1 import java.awt.BorderLayout; 2 import java.awt.GridLayout; 3 import javax.swing.JFrame; 4 import javax.swing.JPanel; 5 import javax.swing.JButton; 6 7 8 public class GuiJPanel extends JFrame 9 { 10 private JPanel buttonJPanel; // painel para armazenar botões 11 private JButton buttons[]; // array de botões 12 private final String names[] = { “Salvar”, “Editar”, “Deletar”, “Sair”}; 13 14 // construtor 15 public GuiJPanel() 16 { 17 super( “Exemplos utilizando JPanel” ); 18 buttons = new JButton[ 4 ]; // cria botões de array 19 20 buttonJPanel = new JPanel(); // cria JPanel 21 buttonJPanel.setLayout( new GridLayout( 1, buttons.length ) ); //configura o layout do JPanel 22 23 // cria e adiciona botões 24 for ( int count = 0; count < buttons.length; count++ ) 25 { 26 buttons[ count ] = new JButton( names [ count ] ) ; 27 buttonJPanel.add( buttons[ count ] ); // adiciona botão ao painel 28 } 29 30 add( buttonJPanel, BorderLayout.SOUTH ); // adiciona painel ao JFrame na região Sul 31 } // fim do construtor 32 33 public static void main( String args[] ) 34 { 35 GuiJPanel panel = new GuiJPanel(); 36 panel.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 37 panel.setSize( 450, 200 ); // configura o tamanho do frame 38 panel.setVisible( true ); // exibe o frame 39 } // fim do main() 40 } // fim da classe 116 Linguagens de Programação II.indb 116 7/12/2006 14:00:46 Linguagens de Programação II Veja a análise de algumas linhas deste código. Linha 20 – cria o componente JPanel. Cada componete JPanel ou panel pode conter outros componentes GUI, inclusive outros JPanel. Linha 21 – cada componente JPanel pode ter seu próprio gerenciador de layout. Nessa linha, o JPanel buttonJPanel configurou o gerenciador de layout para GridLayout através do método setLayout(). Como argumento para o método, é passada uma referência do gerenciador de layout new GridLayout( 1, buttons.length ). No construtor do gerenciador configuramse os componentes nesse JPanel para serem dispostos em uma linha e quatro colunas (buttons.length retorna tamanho do array buttons). Linha 27 – adiciona os componentes JButton ao componente JPanel buttonJPanel. Linha 30 – adiciona o componente JPanel ao container principal, especificando a região onde deve ser adicionado, no caso BorderLayout.SOUTH. A região pode ser especificada porque o gerenciador de layout padrão do container é GridLayout, que dispõe os componentes em cinco regiões. Saiba mais sobre o componente JComboBox! Consulte a documentação referente a este componente em: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ JPanel.html Unidade 4 Linguagens de Programação II.indb 117 117 7/12/2006 14:00:46 Universidade do Sul de Santa Catarina Síntese Nessa unidade você aprendeu a utilizar o componente Swing JTextArea. Aprendeu outra forma de tratar eventos gerados pelos componentes, através da criação de classe interna anônima. Nas últimas seções dessa unidade você conheceu outros tipos de Gerenciadores de Layout, conhecidos como BorderLayout, GridLayout e BoxLayout. Além desses, existem outros gerenciadores que não serão abordados nessas unidades referentes à GUI. Para conhecer mais sobre outros gerenciadores consulte as referências indicadas no final da unidade. Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Modifique a aplicação da atividade de auto-avaliação solicitada na unidade anterior para tratar os eventos utilizando classe interna anônima. 2) Modifique a aplicação da atividade de auto-avaliação solicitada na unidade anterior utilizando o gerenciador de layout GridLayout. 118 Linguagens de Programação II.indb 118 7/12/2006 14:00:46 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando a seguinte referência, principalmente os capítulos 10, 11 e 22: DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. Também consulte: HORSTMANN, Cay; CORNELL, Gary. Core JAVA 2. Volume I – Fundamentos. 7 ed. Rio de Janeiro: Alta Books, 2005. Consulte, também, os seguintes sites: http://java.sun.com/docs/books/tutorial/uiswing/components/panel. html (Como usar Panels) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter3html/ (Frames, Panels, and Borders) Unidade 4 Linguagens de Programação II.indb 119 119 7/12/2006 14:00:46 Linguagens de Programação II.indb 120 7/12/2006 14:00:46 UNIDADE 5 Layout, JTabbedPane e componentes de Menu 5 Objetivos de aprendizagem Aprender a construir GUI com Layout mais Complexo. Conhecer o componente JTabbedPane. Criar GUI com componentes de Menu. Seções de estudo Seção 1 Construindo GUI com Layout mais Complexo II Seção 2 Componente JTabbedPane Seção 3 Criando Menus em uma GUI Linguagens de Programação II.indb 121 7/12/2006 14:00:46 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você aprenderá uma miscelânea de conceitos e componentes GUI. Será dada continuidade ao assunto abordado no capítulo anterior, que tratou de maneira introdutória a construção de uma GUI com layout mais complexo. Neste capítulo, aprofundaremos um pouco mais esse assunto, sem contudo, ter a pretensão de esgotá-lo. A construção de GUI com layout mais elaborado é um assunto que deve ser pesquisado além do que será abordado nesses capítulos. Logo a seguir, outro componente Swing, JTabbedPane será abordado. A escolha de quais componentes abordar nos capítulos referentes à GUI se deu em função de uma maior utilização dos mesmos em construção de GUI. No final dessa unidade são mostrados alguns componentes para a construção de menus em GUI. Seção 1 - Construindo GUI com Layout mais Complexo II A figura 5.1 mostra uma GUI onde vários componentes JPanel foram utilizados para armazenar outros componentes GUI. FIGURA 5.1 – GUI DA APLICAÇÃO GUIJPANEL2 Foram criados quatro componentes JPanel: 122 Linguagens de Programação II.indb 122 7/12/2006 14:00:46 Linguagens de Programação II 1) Um JPanel para adicionar todos os componentes JLabel (lado esquerdo). Nele foi usado o gerenciador GridLayout de 1 coluna. 2) Outro JPanel para adicionar os componentes JTextField (lado direito). Nele também foi usado o gerenciador GridLayout de 1 coluna. 3) Outro JPanel para adicionar os JButton (região sul). Nele foi utilizado o gerenciador GridLayout de 4 colunas. 4) Um JPanel principal foi criado para adicionar todos os outros JPanel, um em cada região desse JPanel. Para isso, ele foi configurado com o gerenciador BorderLayout para esse JPanel. O JPanel dos label´s ficou na região CENTER, o JPanel dos textfield´s ficou na região EAST e o JPanel dos buttons ficou na região SOUTH. O JPane principal foi configurado para aparecer na região CENTER do frame. Não precisamos configurar o gerenciador do JFrame porque seu gerenciador padrão já é BorderLayout. O código da aplicação é exibido a seguir: import java.awt.GridLayout; import java.awt.BorderLayout; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.JButton; import javax.swing.JPanel; public class GuiJPanel2 extends JFrame { private JLabel labelNome; private JLabel labelEndereco; private JLabel labelCidade; private JTextField textfieldNome; private JTextField textfieldEndereco; private JTextField textfieldCidade; private JPanel buttonJPanel; // painel para armazenar botões private JButton buttons[] = new JButton[ 4 ]; // array de botões private final String names[] = { “Salvar”, “Editar”, “Deletar”, “Sair”}; Unidade 5 Linguagens de Programação II.indb 123 123 7/12/2006 14:00:47 Universidade do Sul de Santa Catarina // construtor sem argumento public GuiJPanel2() { super(“Exemplo com Multiplos Paineis”); labelNome = new JLabel(“Nome”); labelEndereco = new JLabel(“Endereço”); labelCidade = new JLabel(“Cidade”); textfieldNome = new JTextField(30); textfieldEndereco = new JTextField(30); textfieldCidade = new JTextField(30); JPanel buttonJPanel = new JPanel(new GridLayout( 0, 4)); // cria JPanel dos botoes // cria e adiciona botões ao panel for ( int count = 0; count < buttons.length; count++ ) { buttons[ count ] = new JButton( names [ count ] ) ; buttonJPanel.add( buttons[ count ] ); // adiciona botão ao painel } JPanel labelPane = new JPanel(new GridLayout(0,1)); // cria JPanel dos labels labelPane.add(labelNome); //adiciona label´s ao panel labelPane.add(labelEndereco); labelPane.add(labelCidade); JPanel fieldPane = new JPanel(new GridLayout(0,1));// cria JPanel dos textedit fieldPane.add(textfieldNome); //adiciona textfield´s ao panel fieldPane.add(textfieldEndereco); fieldPane.add(textfieldCidade); JPanel principalPane = new JPanel(new BorderLayout());// cria JPanel principal principalPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); principalPane.add(labelPane, BorderLayout.CENTER);// adiciona painel ao JFrame na região Sul principalPane.add(fieldPane, BorderLayout.EAST);// adiciona painel ao JFrame na região Sul principalPane.add( buttonJPanel, BorderLayout.SOUTH ); // adiciona painel ao JFrame na região Sul add(principalPane,BorderLayout.CENTER) ; } // fim do construtor public static void main( String args[] ) { GuiJPanel2 panel2 = new GuiJPanel2(); panel2.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); panel2.setSize( 600, 200 ); // configura o tamanho do frame panel2.setVisible( true ); // exibe o frame } // fim de main } // fim da classe 124 Linguagens de Programação II.indb 124 7/12/2006 14:00:47 Linguagens de Programação II A linha em negrito configura uma borda para o componente JPanel principalPane. É invocado o método setBorder() e passado, como argumento, uma borda criada com a classe BorderFactory. createEmptyBorder(10, 10, 10, 10). O método createEmptyBorder() especifica uma borda com dimensões em pixels onde cada argumento representa o seguinte: top (primeiro argumento) - inteiro que especifica o comprimento em relação ao topo do componente. left (segundo argumento) - inteiro que especifica o comprimento do lado esquerdo. bottom (terceiro argumento) - inteiro que especifica o comprimento em relação à base do componente. right (terceiro argumento) - inteiro que especifica o comprimento em relação ao lado direito. Seção 2 – Componente JTabbedPane O componente JTabbedPane permite que várias guias ou abas sejam inseridas nele. Cada aba ou guia pode conter outro componente GUI, provavelmente um componente do tipo container, como um JPanel. Você já sabe que em um JPanel podem ser inseridos outros componentes GUI. Com isso, cada guia pode exibir um conjunto de componentes em um layout específico. Unidade 5 Linguagens de Programação II.indb 125 125 7/12/2006 14:00:47 Universidade do Sul de Santa Catarina Uma guia pode ser exibida por vez. O padrão é que elas apareçam na parte superior do componente, mas podem ser configuradas para aparecer à esquerda, direita ou parte inferior. A figura 5.2 mostra uma aplicação onde quatro guias estão disponíveis. Em cada uma delas foi inserido um JPanel que, por sua vez, teve inserido um JLabel. Isso faz com que, ao exibir cada guia, um texto apareça no centro do panel. A tecla de atalho de cada guia está marcada com underline. Isso faz que com que ela possa ser acessada com a combinação de Alt + caracter com underline. Na aba de cada guia, você pode configurar o nome desejado, inserir uma imagem e configura uma tecla de atalho para acessar a própria guia. FIGURA 5.2 – GUI DA APLICAÇÃO GUIJTABBEDPANE O código da aplicação é exibido a seguir: import javax.swing.JTabbedPane; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JFrame; import java.awt.GridLayout; Cria o componente JTabbedPane. Criar o objeto que representa a imagem. public class GuiJTabbedPane extends JFrame { public GuiJTabbedPane() { super(“Exemplo de JTabbedPane”); JTabbedPane tabbedPane = new JTabbedPane(); ImageIcon icon = new ImageIcon(“middle.gif”); 126 Linguagens de Programação II.indb 126 7/12/2006 14:00:47 Linguagens de Programação II JPanel panel1 = new JPanel(false); JLabel label1 = new JLabel(“Texto da guia 1”); label1.setHorizontalAlignment(JLabel.CENTER); panel1.setLayout(new GridLayout(1, 1)); panel1.add(label1); tabbedPane.addTab(“Aba 1”, icon, panel1,”Primeira guia”); tabbedPane.setMnemonicAt(0, ‘1’); - Cria um JPanel - Cria um JLabel com um texto que aparecerá no JPanel - Configura o alinhamento do texto no JLabel - Configura o layout do JPanel para GridLayout de uma linha e uma coluna - Adiciona o JLabel ao JPanel - Adiciona uma nova guia ao componente JTabbedPane - Configura a tecla de atalho para acessar a guia. JPanel panel2 = new JPanel(false); JLabel label2 = new JLabel(“Texto da guia 2”); label2.setHorizontalAlignment(JLabel.CENTER); panel2.setLayout(new GridLayout(1, 1)); panel2.add(label2); tabbedPane.addTab(“Aba 2”, icon, panel2,”Segunda guia”); tabbedPane.setMnemonicAt(1, ‘2’); JPanel panel3 = new JPanel(false); JLabel label3 = new JLabel(“Texto da guia 3”); label3.setHorizontalAlignment(JLabel.CENTER); panel3.setLayout(new GridLayout(1, 1)); panel3.add(label3); tabbedPane.addTab(“Aba 3”, icon, panel3,”Terceira guia”); tabbedPane.setMnemonicAt(2, ‘3’); JPanel panel4 = new JPanel(false); JLabel label4 = new JLabel(“Texto da guia 4”); label4.setHorizontalAlignment(JLabel.CENTER); panel4.setLayout(new GridLayout(1, 1)); panel4.add(label4); tabbedPane.addTab(“Aba 4”, icon, panel4,”Quarta guia”); tabbedPane.setMnemonicAt(3, ‘4’); //Adiciona o JTabbedPane para o frame. add(tabbedPane); } public static void main(String[] args) { GuiJTabbedPane tabbedpane = new GuiJTabbedPane(); tabbedpane.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); tabbedpane.setSize( 350, 200 ); // configura o tamanho do frame tabbedpane.setVisible( true ); // exibe o frame } } Unidade 5 Linguagens de Programação II.indb 127 127 7/12/2006 14:00:47 Universidade do Sul de Santa Catarina Veja, agora, os comentários de algumas linhas do código. As linhas em negrito inserem uma guia nova no componente JTabbedPane. Isso é feito com o método addTab(). São passados, como argumento, os seguintes itens: String com o título da aba; Objeto do tipo Icon que representa uma imagem. Caso você não deseje inserir uma imagem na aba, passe null. Componente que será inserido na aba. Normalmente, ele é um componente do tipo JPanel que já tenha sido criado e com outros componentes adicionados a ele. String com o texto que será apresentado quando o usuário passar o mouse em cima da aba. Dica de ferramenta. O método addTab() pode ser invocado passando-se apenas a String com o título da aba e o componente a ser inserido. Depois de adicionar a nova aba é configurado o caractere que servirá como tecla de atalho para acessá-la mais rapidamente. Isso é feito com o método setMnemonicAt (0, ‘1’). É passado, como argumento, o índice da aba (que sempre começa em 0) e o caractere de atalho. Seção 3 – Criando Menus em uma GUI Em uma GUI, os menus permitem que o usuário escolha opções, as quais produzem ações como abrir uma janela com outros componentes GUI, exibir uma caixa de diálogo, etc. As classes utilizadas para construir menus são: JMenu: menu de nível mais alto, por exemplo Arquivo e Formatar. Contém os itens de menu e são adicionados à barra de menus (JMenuBar). Quando um menu é clicado, sua lista de itens é mostrada. 128 Linguagens de Programação II.indb 128 7/12/2006 14:00:48 Linguagens de Programação II JMenuItem: item de menu que está dentro de um JMenu. Quando um item de menu é clicado, uma ação é executada. Um item de menu pode ser um submenu com mais itens de menu. JMenuBar: componente onde os JMenu – Arquivo, Formatar – são inseridos. É o container dos menus. JCheckBoxMenuItem: itens de menu no formato checkbox, ou seja, itens que podem ser ativados ou desativados. JRadioButtonMenuItem: itens de menu no formato radiobutton. Esses itens também podem ser ativados ou desativados. As figuras, a seguir, mostram uma GUI de uma aplicação que usa menus. O objetivo da aplicação é formatar o texto “Texto de Exemplo” que aparece na área central do frame. Nessa aplicação aparecem dois menus: Arquivo e Formatar. Dentro do menu Arquivo aparecem dois itens de menu: Sobre.. e Sair. Ao clicar na opção “Sobre”, do menu Arquivo, uma caixa de diálogo deve aparecer. Ao clicar na opção “Sair”, do menu Arquivo, a aplicação termina. Dentro do menu Formatar aparecem dois itens de menu que também são submenus: Cor e Fonte. Ao clicar no item “Cor”, o submenu no formato de botões de rádio com o nome das cores aparece. Ao clicar no item “Fonte”, um submenu no formato de botões de rádio com o nome de fontes e no formato de checkbox com os estilos aparece. JMenuBar JMenu JMenuItem FIGURA 5.3 – GUI DA APLICAÇÃO GUIJMENU Unidade 5 Linguagens de Programação II.indb 129 129 7/12/2006 14:00:48 Universidade do Sul de Santa Catarina JRadioButtonMenuItem FIGURA 5.4 – GUI DA APLICAÇÃO GUIJMENU JCheckBoxMenuItem FIGURA 5.5 – GUI DA APLICAÇÃO GUIJMENU Veja, a seguir, o código da aplicação. 1 import java.awt.Color; 2 import java.awt.Font; 3 import java.awt.BorderLayout; 4 import java.awt.event.ActionListener; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ItemListener; 7 import java.awt.event.ItemEvent; 8 import javax.swing.JFrame; 9 import javax.swing.JRadioButtonMenuItem; 10 import javax.swing.JCheckBoxMenuItem; 11 import javax.swing.JOptionPane; 12 import javax.swing.JLabel; 13 import javax.swing.SwingConstants; 14 import javax.swing.ButtonGroup; 15 import javax.swing.JMenu; 16 import javax.swing.JMenuItem; 17 import javax.swing.JMenuBar; 18 19 public class GuiJMenu extends JFrame 20 { 21 private final Color colorValues[] = { Color.BLACK, Color.BLUE, Color.RED, Color.GREEN }; 22 private JRadioButtonMenuItem colorItems[]; // itens do menu Cor 130 Linguagens de Programação II.indb 130 7/12/2006 14:00:48 Linguagens de Programação II 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 private JRadioButtonMenuItem fonts[]; // itens do menu Fonte private JCheckBoxMenuItem styleItems[]; // itens do menu Fonte Estilo private JLabel displayJLabel; // exibe texto de exemplo private ButtonGroup fontButtonGroup; // gerencia itens do menu Fonte private ButtonGroup colorButtonGroup; // gerencia itens do menu Cor private int style; // utilizado para criar estilos de fontes public GuiJMenu() { super( “Exemplo com JMenu” ); JMenu arquivoMenu = new JMenu( “Arquivo” ); // cria o menu Arquivo arquivoMenu.setMnemonic( ‘A’ ); // configura o mnemônico como A // cria item de menu Sobre... JMenuItem sobreItem = new JMenuItem( “Sobre...” ); sobreItem.setMnemonic( ‘S’ ); // configura o mnemônico com A arquivoMenu.add(sobreItem); // adiciona o item Sobre ao menu Arquivo sobreItem.addActionListener( new ActionListener() { // classe interna anônima // exibe um diálogo de mensagem quando o usuário seleciona Sobre... public void actionPerformed( ActionEvent event ) { JOptionPane.showMessageDialog( GuiJMenu.this, “Exemplo de GUI com menus”, “Sobre”, JOptionPane.PLAIN_MESSAGE ); } // fim do método actionPerformed } // fim da classe interna anônima ); // fim da chamada para addActionListener JMenuItem sairItem = new JMenuItem( “Sair” ); // cria o item Sair sairItem.setMnemonic( ‘S’ ); // configura o mnemônico como S arquivoMenu.add(sairItem); // adiciona o item Sair ao menu Arquivo sairItem.addActionListener( new ActionListener() // classe interna anônima { // termina o aplicativo quando o usuário clica Sair public void actionPerformed( ActionEvent event ) { System.exit( 0 ); // encerra o aplicativo } // fim do método actionPerformed } // fim da classe interna anônima ); // fim da chamada para addActionListener JMenuBar bar = new JMenuBar(); // cria a barra de menus setJMenuBar( bar ); // adiciona uma barra de menus ao aplicativo bar.add(arquivoMenu); // adiciona o menu File à barra de menus JMenu formatMenu = new JMenu( “Formatar” ); // cria o menu Formatar formatMenu.setMnemonic( ‘F’ ); // configura o mnemônico como F Unidade 5 Linguagens de Programação II.indb 131 131 7/12/2006 14:00:48 Universidade do Sul de Santa Catarina 78 // array listando cores de string 79 String colors[] = { “Preto”, “Azul”, “Vermelho”, “Verde” }; 80 81 JMenu corMenu = new JMenu( “Cor” ); // cria o menu Cor 82 corMenu.setMnemonic( ‘C’ ); // configura o mnemônico como C 83 84 // cria itens do menu Cor com botões de opção 85 colorItems = new JRadioButtonMenuItem[ colors.length ]; 86 colorButtonGroup = new ButtonGroup(); // agrupador de botões 87 88 TrataEventoBotao tratabotao = new TrataEventoBotao(); // ouvinte de evento para os botoes 89 90 // cria itens do menu Cor com botões de opção 91 for ( int count = 0; count < colors.length; count++ ) 92 { 93 colorItems[ count ] = new JRadioButtonMenuItem( colors[ count ] ); // cria o item 95 corMenu.add( colorItems[ count ] ); // adiciona o item ao menu Cor 96 colorButtonGroup.add( colorItems[ count ] ); // adiciona ao grupo 97 colorItems[ count ].addActionListener( tratabotao ); //adiciona o ouvinte a cada botao 98 } // fim do for 99 100 colorItems[ 0 ].setSelected( true ); // seleciona o primeiro item dos botões de cor 101 102 formatMenu.add( corMenu ); // adiciona o menu Cor ao menu Format 103 formatMenu.addSeparator(); // adiciona um separador no menu 104 105 // array listando nomes de fonte 106 String fontNames[] = { “Serif”, “Monospaced”, “SansSerif” }; 107 JMenu fontMenu = new JMenu( “Fonte” ); // cria a fonte do menu 108 fontMenu.setMnemonic( ‘n’ ); // configura o mnemônico como n 109 110 // cria itens do menu radiobutton para nomes de fonte 111 fonts = new JRadioButtonMenuItem[ fontNames.length ]; 112 fontButtonGroup = new ButtonGroup(); // agrupador dos botoes das fontes 113 114 // criar itens do menu Font com botões de opção 115 for ( int count = 0; count < fonts.length; count++ ) 116 { 117 fonts[ count ] = new JRadioButtonMenuItem( fontNames[ count ] ); 118 fontMenu.add( fonts[ count ] ); // adiciona fonte ao menu Font 119 fontButtonGroup.add( fonts[ count ] ); // adiciona ao grupo de botões 120 fonts[ count ].addActionListener( tratabotao ); // adiciona handler 121 } // fim do for 122 123 fonts[ 0 ].setSelected( true ); // seleciona o primeiro item do menu Font 124 fontMenu.addSeparator(); // adiciona uma barra separadora ao menu Font 125 126 String styleNames[] = { “Bold”, “Italic” }; // nomes dos estilos 127 styleItems = new JCheckBoxMenuItem[ styleNames.length ]; 128 TrataEventoCheckBox tratacheck = new TrataEventoCheckBox(); // ouvinte de evento para JChec 129 130 // criar itens do menu Style com caixas de seleção 132 Linguagens de Programação II.indb 132 7/12/2006 14:00:49 Linguagens de Programação II 131 for ( int count = 0; count < styleNames.length; count++ ) 132 { 133 styleItems[ count ] = new JCheckBoxMenuItem( styleNames[ count ] ); // para estilo 134 fontMenu.add( styleItems[ count ] ); // adiciona ao menu Font 135 styleItems[ count ].addItemListener( tratacheck ); // handler 136 } // fim do for 137 138 formatMenu.add( fontMenu ); // adiciona o menu Fonte ao menu Formatar 139 bar.add( formatMenu ); // adiciona o menu Formatar à barra de menus 140 141 // configura o rótulo para exibir texto 142 displayJLabel = new JLabel( “Texto de Exemplo”, SwingConstants.CENTER ); 143 displayJLabel.setForeground( colorValues[ 0 ] ); 144 displayJLabel.setFont( new Font( “Serif”, Font.PLAIN, 72 ) ); 145 146 getContentPane().setBackground( Color.CYAN ); // configura o fundo 147 add( displayJLabel, BorderLayout.CENTER ); // adiciona displayJLabel 148} // fim do construtor 149 150 //classe interna para tratar eventos de ação dos itens de menu 151 private class TrataEventoBotao implements ActionListener 152 { 153 // processa seleções de cor e fonte 154 public void actionPerformed( ActionEvent event ) 155 { 156 // processa a seleção de cor 157 for ( int count = 0; count < colorItems.length; count++ ) 158 { 159 if ( colorItems[ count ].isSelected() ) 160 { 161 displayJLabel.setForeground( colorValues[ count ] ); 162 break; 163 } // fim do if 164 } // fim do for 165 166 // processa a seleção de fonte 167 for ( int count = 0; count < fonts.length; count++ ) 168 { 169 if ( event.getSource() == fonts[ count ] ) 170 { 171 displayJLabel.setFont( new Font( fonts[ count ].getText(), style, 72 ) ); 173 } 174 } // fim do for 175 176 repaint(); // redesenha o aplicativo 177 } // fim do método actionPerformed 178} // fim da classe interna 179 180 // classe interna para tratar eventos dos itens de menu com caixa de seleção 181 private class TrataEventoCheckBox implements ItemListener 182 { Unidade 5 Linguagens de Programação II.indb 133 133 7/12/2006 14:00:49 Universidade do Sul de Santa Catarina 183 // processa seleções de estilo da fonte 184 public void itemStateChanged( ItemEvent e ) 185 { 186 style = 0; // inicializa o estilo 187 // verifica se negrito foi selecionado 188 if ( styleItems[ 0 ].isSelected() ) 189 style += Font.BOLD; // adiciona negrito ao estilo 190 191 // verifica se itálico foi selecionado 192 if ( styleItems[ 1 ].isSelected() ) 193 style += Font.ITALIC; // adiciona itálico ao estilo 194 195 displayJLabel.setFont(new Font( displayJLabel.getFont().getName(), style, 72 ) ); 197 repaint(); // redesenha o aplicativo 198 } // fim do método 199} // fim da classe interna 200 201 202 203 public static void main( String args[] ) 204 { 205 GuiJMenu menu = new GuiJMenu(); // criar MenuFrame 206 menu.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); 207 menu.setSize( 580, 200 ); // configura o tamanho do frame 208 menu.setVisible( true ); // exibe o frame 209 } // fim do main() 210 211} // fim da classe GuiJMenu Acompanhe, a seguir, alguns comentários pertinentes às linhas de programação do quadro anteriormente apresentado: Linha 21 - cria um array de objetos do tipo Color. Nesse array estão as cores disponíveis para modificar a cor da fonte do texto. Linha 22 - cria um array para armazenar os itens de menu do tipo botão de rádio. Esse array é do tipo JRadioButtonMenuItem. Esses itens de menu irão configurar a cor da fonte. Linha 23 - cria um array para armazenar os itens de menu do tipo botão de rádio. Esse array é do tipo JRadioButtonMenuItem. Esses itens de menu irão configurar o tipo da fonte. Linha 24 - cria um array para armazenar os itens de menu do tipo checkbox. Esse array é do tipo JCheckBoxMenuItem. Esses itens de menu irão configurar o estilo da fonte. 134 Linguagens de Programação II.indb 134 7/12/2006 14:00:49 Linguagens de Programação II Linhas 26 e 27 - criar os objetos do tipo ButtonGroup para agrupar os itens de menu JRadioButtonMenuItem que representam as cores e o tipo da fonte. Linha 34 - cria o menu Arquivo com o componente JMenu. Primeiramente, deve-se criar o menu com JMenu, depois deve criar os itens de menu com JMenuItem. Linha 35 - configura o caractere (mnemônico) que servirá de tecla de atalho. O método é setMnemonic( ‘A’ ). É passado como argumento do caractere (deve estar em aspas simples) que servirá como tecla de atalho para esse menu. Linhas 37 e 38 - cria o primeiro item de menu do menu Arquivo. Um item de menu deve ser criado com JMenuItem. Esse é o item de menu “Sobre...”. Na linha 38 é configurado o caractere que servirá como tecla de atalho. Linha 41 - adiciona o item de menu “Sobre..” ao menu “Arquivo”. Isso é feito através do método add() de arquivoMenu. É passado, como argumento, o objeto item de menu sobreItem. Linha 42 - adiciona um objeto ouvinte de evento ao item de menu sobreItem recém- criado. Isso é necessário porque quando o usuário clicar nesse item de menu, queremos que uma caixa de diálogo com informações sobre a aplicação apareça. A figura 5.6 ilustra o aparecimento dessa caixa. FIGURA 5.6 – CAIXA DE DIÁLOGO DA APLICAÇÃO Linha 43 - o objeto ouvinte de evento é criado dentro do método addActionListener( ) com a instrução new ActionListener(). Note que os parênteses do método addActionListener começam na linha 42 e terminam na linha 53. Ele deve ser um objeto do tipo ActionListener porque a interação do usuário com um item de menu gera um evento do tipo ActionEvent. Unidade 5 Linguagens de Programação II.indb 135 135 7/12/2006 14:00:49 Universidade do Sul de Santa Catarina Você lembra quais outras interações com componentes GUI geram esse tipo de evento? Clicar com o mouse em um JButton, pressionar a tecla Enter em um JTextField. Linhas 44 a 52 - a classe do objeto ouvinte de evento ActionListener começa a ser implementada na linha 44, a partir do símbolo de {. É uma classe interna anônima. Você trabalhou com esse tipo de classe nas aplicações anteriores. Ela termina da linha 52, no símbolo de }. Dentro dessa classe, está implementado o método actionPerformed() e, dentro dele, programamos para uma caixa de diálogo aparecer. A instrução que faz aparecer a caixa de diálogo está na linha 48. Note que quando usamos essa caixa de diálogo nas aplicações anteriores, o primeiro argumento sempre era null. Esse primeiro argumento especifica a janela pai onde a caixa de diálogo irá aparecer. Nas aplicações anteriores, não tínhamos essa janela pai, por isso o argumento era null e a caixa de diálogo aparecia no centro da tela. Nesse caso, especificamos que a janela pai é a classe GuiJMenu.this (this faz referência ao próprio objeto GuiJMenu), logo a caixa de diálogo aparecerá centralizada nessa janela. Precisamos especificar this depois da classe porque estamos dentro de uma classe interna. Esse tipo de caixa de diálogo é conhecida como caixa de diálogo modal. Uma caixa de diálogo modal não permite acessar qualquer outra janela do aplicativo até que ela seja fechada. - A partir desta explicação, tente fazer uma experiência com essa caixa de diálogo... Você conseguiu acessar a janela pai? Linhas 55 e 56 - cria o segundo item de menu sairItem. Na próxima linha, é configurado o caractere que servirá como tecla de atalho para o item de menu “Sair”. 136 Linguagens de Programação II.indb 136 7/12/2006 14:00:49 Linguagens de Programação II Linha 58 - adiciona o item de menu sairItem ao menu arquivoMenu através do método add() de arquivoMenu. É passado, como argumento, o item de menu que deve ser adicionado. Linha 59 - adiciona um objeto ouvinte de evento ao item de menu sairItem. Todos os objetos ouvintes de eventos que forem adicionados a objetos itens de menu serão feitos com o método addActionListener(). Por isso, a explicação é a mesma das linhas anteriores. A classe interna desse objeto ouvinte começa na linha 61 e termina na linha 67. Dentro do método actionPerformed() foi programada a instrução System.exit(0), que faz com que aplicação GUI termine, pois é isso que queremos que aconteça quando o usuário clicar no item de menu Sair. Linha 70 - cria o componente barra de menus JMenuBar, onde serão inseridos os dois menus criados anteriormente com JMenu (Arquivo e Formatar). Linha 71 - a barra de menus deve ser adicionada ao JFrame com o método setJMenuBar(). É passado, como argumento, o componente JMenuBar bar criado na linha anterior. Linha 72 - O método bar.add(arquivoMenu) adiciona à barra de menu JMenuBar bar o primeiro menu arquivoMenu. Linha 74 e 75 - é criado o segundo menu “Formatar” com o componente JMenu. É configurado o caractere de atalho para esse menu. Linha 79 - array de String colors[] é criado e inicializado com o nome das quatro cores que aparecerão no menu Formatar. Linha 81 e 82 - é criado um outro menu chamado Cor. Isso é feito com o componente JMenu, porém esse menu aparecerá dentro do menu Formatar, por isso, ele é chamado de submenu. Na próxima linha, é configurado o caractere de atalho para esse submenu. Linha 85 - os itens do submenu cor não são criados com JMenuItem. Como são itens de menu do tipo botão de rádio, eles são criados usando o componente JRadioButtonMenuItem. Como em vários itens de menu desse tipo, é criado um array chamado colorItems do tipo JRadioButtonMenuItem. O Unidade 5 Linguagens de Programação II.indb 137 137 7/12/2006 14:00:50 Universidade do Sul de Santa Catarina tamanho do array é determinado em função do tamanho do array colors[], criado na linha 79. Linha 86 - é criado um objeto agrupador dos itens de menu JRadioButtonMenuItem. Esse objeto é chamado de colorButtonGroup e é do tipo ButtonGroup(). Você já usou o agrupador ButtonGroup quando foi apresentado ao componente JRadioButton nos capítulos anteriores. Linha 88 - cria um objeto ouvinte de evento do tipo ActionListener. Esse objeto tem este tipo porque a classe TrataEventoBotao da linha 151 implementa a classe ActionListener e porque os eventos gerados pelos itens de menu JRadioButtonMenuItem são do tipo ActionEvent. Linhas 91 a 98 - inícia o for com várias instruções: 93 - cria o item de menu do tipo JRadioButtonMenuItem e armazena no array colorItems. 95 - adiciona o item de menu recém-criado ao JMenu corMenu (criado na linha 81). 96 - adiciona o item de menu recém-criado ao agrupador de itens de menu do tipo botão de rádio. 97 - adiciona o objeto ouvinte de evento criado na linha 88 a este item de menu criado. Quando o usuário clicar num item de menu desse tipo, o código das linhas 156 a 176 será executado. Nessas linhas, mais especificamente entre as linhas 157 e 164, é verificado qual o componente JRadioButtonMenuItem foi selecionado (método isSelected()). Conforme o componente selecionado, a cor será aplicada no texto do componente JLabel, mudando, com isso, a cor da fonte desse texto. Atenção! Esse “for” repetirá o número de vezes correspondente ao número de elementos do array colors[]. Nesse caso, repetirá quatro vezes, visto que são quatro botões itens de menu, cada um representando uma cor específica. 138 Linguagens de Programação II.indb 138 7/12/2006 14:00:50 Linguagens de Programação II Linha 100 - configura para que o primeiro item de menu (o que está na posição 0 do array colorItems[ ]) seja selecionado. Linha 102 - adiciona o JMenu corMenu (que contém os itens de menu do tipo botão de rádio) ao JMenu formatMenu através do método add(). Linha 103 - adiciona uma linha separadora de menus ao JMenu formatMenu. Isso é feito com o método addSeparator(); Linha 106 - cria array de String com o nome das fontes que serão utilizadas para configuração. Linha 107 - cria o submenu Fonte com o componente JMenu. Nesse submenu, serão adicionados outros itens de menu para configuração do tipo e estilo da fonte do texto. Logo após, é configurado o caractere de atalho para esse submenu. Linha 111 - cria o array para armazenar os itens de menu do tipo radiobutton que representarão os nomes de fonte que poderão ser escolhidas. Esse array tem o mesmo tamanho que o array fontNames[], criado na linha 106. Linha 112 - é criado um objeto agrupador desses itens de menu JRadioButtonMenuItem. Esse objeto é chamado de fontButtonGroup e é do tipo ButtonGroup(). Linhas 115 a 121 - inicia o for com várias instruções: 117 - cria um item de menu do tipo JRadioButtonMenuItem e armazena no array fonts. 118 - adiciona o item de menu recém-criado ao JMenu fontMenu (criado na linha 107). 119 - adiciona o item de menu recém-criado ao agrupador de itens de menu do tipo botão de rádio. 120 - adiciona o objeto ouvinte de evento criado na linha 88 a esse item de menu criado. Quando o usuário clicar num item de menu desse tipo, o código das linhas 156 a 176 será executado. Nessas linhas, mais especificamente entre as linhas 167 e 174, é verificado qual o componente JRadioButtonMenuItem foi selecionado (método Unidade 5 Linguagens de Programação II.indb 139 139 7/12/2006 14:00:50 Universidade do Sul de Santa Catarina isSelected()). Conforme o componente selecionado, um tipo de fonte será aplicada no texto do componente JLabel, mudando, com isso, o tipo da fonte desse texto. Linha 123 - configura para que o primeiro item de menu (o que está na posição 0 do array fonts[ ]) seja selecionado. Linha 124 - adiciona uma linha separadora no JMenu fontMenu. Linha 126 - array de String styleNames [] é criado e inicializado com o nome dos dois estilos de fontes que aparecerão no submenu Fonte. Linha 127 - cria o array para armazenar os itens de menu do tipo checkbox que representarão os estilos de fonte que poderão ser escolhidas. Esse array tem o mesmo tamanho que o array styleNames [], criado na linha 126. Linha 128 - cria um objeto ouvinte de evento do tipo ItemListener. Esse objeto é desse tipo porque a classe TrataEventoCheckBox, da linha 181, implementa a classe ItemListener e porque os eventos gerados pelos itens de menu JCheckBoxMenuItem são do tipo ItemEvent. Linhas 131 a 136 - início do for com várias instruções: 133 - cria um item de menu do tipo JCheckBoxMenuItem e armazena no array styleItems. 134 - adiciona o item de menu recém-criado ao JMenu fontMenu (criado na linha 107). 135 - adiciona o objeto ouvinte de evento criado na linha 128 a esse item de menu criado. Quando o usuário clicar num item de menu desse tipo, os códigos das linhas 186 a 198 serão executados. Nessas linhas, é verificado qual o componente JCheckBoxMenuItem foi selecionado (método isSelected()). Conforme o componente selecionado (componente que gera o evento), um estilo de fonte será aplicada no texto do componente JLabel, mudando, com isso, o estilo da fonte desse texto. 140 Linguagens de Programação II.indb 140 7/12/2006 14:00:50 Linguagens de Programação II Linha 138 - adicionar o JMenu fontMenu ao JMenu formatMenu. Isso faz com que fontMenu se torne um submenu. Um JMenu adicionado a outro JMenu. Linha 139 - adicionar o JMenu formatMenu (de nível mais alto) a barra de menus JMenuBar bar. Linha 142 - Cria o componente JLabel com o texto “Texto de Exemplo” . Linha 143 - configura a cor inicial do JLabel para a primeira cor do array colorValues[ 0 ], nesse caso, Color.BLACK (preto). Linha 144 - configure a fonte inicial do JLabel para “Serif ”, sem estilo (Font.PLAIN) e tamanho 72. Linha 146 - recuperar o painel de conteúdo padrão do frame e configurar a cor de fundo para Color.BLUE. Linha 147 - adicionar o componente JLabel displayJLabel ao frame, posicionando na região CENTER. Lembre-se que o gerenciador de layout padrão do frame é BorderLayout. No caso dessa aplicação, o gerenciador é esse, pois não especificamos nenhum outro. Observe que as linhas acima explicam o código da aplicação GuiJMenu. Síntese Nesta unidade, você aprendeu um pouco mais sobre a construção de GUI com layout mais complexo e conheceu mais alguns componentes que são bastante utilizados nas construções de GUI´s. É necessário reforçar que os tópicos referentes à construção de GUI´s não foram esgotados nesses cinco capítulos apresentados até o momento. A intenção foi dar uma introdução ao assunto, abordando os principais conceitos e componentes. Unidade 5 Linguagens de Programação II.indb 141 141 7/12/2006 14:00:50 Universidade do Sul de Santa Catarina Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Construa uma GUI com o componente JTabbedPane. Esse componente deve possuir duas abas (guias) com os rótulos: Cadastro e Consulta. Ao clicar na aba Cadastro a GUI exibida na figura 5.1 deve aparecer. 2) Construa uma GUI com menus com essa aparência. Saiba mais Aprofunde os conteúdos estudados nesta unidade, consultando os seguintes sites: http://www.netbeans.org/ (IDE NetBeans – Ferrramenta com recurso para criação de GUI) http://java.sun.com/docs//books/tutorial/uiswing/components/ tabbedpane.html (How to Use Tabbed Panes) 142 Linguagens de Programação II.indb 142 7/12/2006 14:00:51 UNIDADE 6 Modelando o Banco de Dados 6 Objetivos de aprendizagem Compreender o modelo de dados que será implementado. Exportar o modelo de banco de dados para uma ferramenta de SGDB. Gerar um script de banco de dados. Criar o banco de dados no MYSQL. Seções de estudo Seção 1 Definição de problema. Seção 2 Apresentando o problema. Seção 3 Criando o modelo lógico do banco de dados. Seção 4 Gerando o modelo físico de banco de dados. Seção 5 Criando o Script SQL do banco de dados. Linguagens de Programação II.indb 143 7/12/2006 14:00:51 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você fará a migração de um problema real para uma ferramenta de gerenciamento de banco de dados. Os problemas que podem ser transportados para uma ferramenta de banco de dados, ou de forma resumida, um SGDB, são dos mais variados tipos e complexidades. Porém, nesta unidade, o problema a ser analisado e implementado está diretamente relacionado ao processo de criação e implementação de um software, a gerência de projetos. O modelo apresentado é uma representação simplificada do que é a gerência de um projeto e tem como principal finalidade permitir que você possa criar um software em Java, que, por sua vez, permita o monitoramento de projetos, independentes da área de atuação. Para formalização do modelo físico do banco de dados, será usado o SGDB MySQL, mas a solução pode ser adaptada para qualquer tipo de SGDB. Portanto, mãos à obra. Seção 1 – Definição de problema Se você buscar em alguns dicionários da língua portuguesa a palavra “problema”, encontrará algo como: Problema: questão que se propõe para ser resolvida; algo difícil de explicar; dúvida; questão; mistério; enigma, etc. 144 Linguagens de Programação II.indb 144 7/12/2006 14:00:51 Linguagens de Programação II - Até aí, não há nenhuma novidade nesta definição de problema, certo? Porém, qual a relação entre a palavra problema e as tarefas executadas por um profissional de informática, em especial aqueles que possuem como principal objetivo a implementação de softwares? Pois bem, o profissional de informática envolvido com o desenvolvimento de sistemas computacionais, ou simplesmente softwares, precisa realizar uma tarefa muito complexa, que é compreender as necessidades do cliente a partir do problema apresentado. Este profissional é responsável pelo desenvolvimento e manutenção de sistemas de informação para qualquer tipo de organização, seja ela pública ou privada, de grande porte ou não. A análise detalhada do problema é fundamental para se levantar os requisitos necessários para que o software a ser implementado atenda realmente às necessidades dos seus usuários ou, em outras palavras, solucione os seus problemas. A análise do problema tem como principais finalidades: o levantamento de requisitos; a modelagem e especificação das funcionalidades e delimitações do sistema; a definição dos módulos do sistema. A partir desta análise das necessidades do cliente, é possível: definir em qual plataforma (sistema operacional, ferramenta de banco de dados e linguagem de programação) o sistema será desenvolvido; apresentar um Projeto Lógico e um Projeto Físico para implementação e funcionamento do sistema; prever o período de testes e treinamento dos usuários e, quando necessário, indicar as melhores soluções para a manutenção do sistema. Unidade 6 Linguagens de Programação II.indb 145 145 7/12/2006 14:00:51 Universidade do Sul de Santa Catarina Uma observação importante é que existe uma diferença muito clara entre projeto lógico e projeto físico, conforme é mostrado na tabela a seguir: Quadro 1 - COMPARATIVO ENTRE PROJETO LÓGICO E PROJETO FÍSICO. Projeto Lógico Projeto Físico O objetivo do projeto lógico é a especificação detalhada dos elementos do software a nível lógico, sem se preocupar com as ferramentas que serão utilizadas. Tendo como base o projeto lógico, o objetivo do projeto físico é detalhar os elementos do software a nível físico, preocupando-se com as ferramentas computacionais que serão utilizadas. A finalidade do projeto lógico é a captação das informações, análise e correções; A finalidade do projeto físico é a especificação técnica completa do software, visando à sua implementação, como linguagem de programação e o sistema de banco de dados utilizado. Veja que, com base na introdução acima, nesta unidade o processo de análise do problema e construção do modelo de dados lógico não será realizado por você, pois a finalidade principal, agora, é a construção do modelo numa ferramenta computacional, utilizando o MySQL e o Java. Por se tratar de uma unidade mais prática do que teórica, o processo de levantamento de requisitos foi realizado por nós, como se estivéssemos trabalhando em uma equipe de desenvolvimento, na qual o nosso papel é o de análise de sistemas e o seu papel é o de programador e especialista em banco de dados. Com certeza a sua análise e, principalmente, a representação do problema, através de um modelo de dados, não seria a mesma que a nossa, pois cada um possui uma forma pessoal de analisar e compreender o problema. Na próxima seção, será apresentado o problema de forma clara. Até lá. 146 Linguagens de Programação II.indb 146 7/12/2006 14:00:52 Linguagens de Programação II Seção 2 – Apresentando o problema Até aqui, você já estudou um pouco sobre a tarefa de levantamento de requisitos de um sistema. A partir desta seção, você terá o primeiro contato com o problema sugerido para ser analisado, especificado e, principalmente, solucionado na forma de um sistema computacional, ou, simplesmente, um software. Acompanhe com atenção esse processo! O problema Um projeto, independente da área de atuação, envolve um grande número de participantes que são monitorados pelos gerentes de projetos. Cada integrante da equipe de desenvolvimento do projeto funciona como uma peça importante para que se obtenha o resultado esperado. Mas o que é um projeto? De uma forma bem geral, um projeto é qualquer atividade exercida por uma ou várias pessoas que possuam as seguintes propriedades: uma descrição; uma data de início e uma previsão de término; um controle de andamento; uma representação da situação do projeto. Desta forma, é essencial que estas informações sejam cadastradas e atualizadas periodicamente durante a execução do projeto, para que este esteja sempre representando as realidades das atividades em execução ou já executadas. Unidade 6 Linguagens de Programação II.indb 147 147 7/12/2006 14:00:52 Universidade do Sul de Santa Catarina Um projeto pode conter mais de um Integrante? Como apresentado na descrição do que é um projeto, normalmente existem várias pessoas envolvidas em um projeto, que precisam estar em total sintonia, de forma que cada um saiba como estão sendo realizadas as tarefas de cada integrante. Lembre-se que cada uma representa uma peça em um grande quebra-cabeça em que, juntando-se as peças de forma correta, chegar-se-á ao resultado esperado. Acreditamos que você tenha chegado à seguinte conclusão: A gerência de um projeto envolve o projeto em si, os seus participantes e a relação entres eles. Levantamento dos dados Com base no problema anteriormente relatado, podem-se fazer alguns levantamentos importantes, como: o sistema deverá ter um controle dos projetos cadastrados; o sistema deverá permitir o cadastramento de dados dos projetos, dos participantes e a relação entre cada projeto e seus participantes; o sistema deverá possibilitar a atualização dos dados dos projetos, principalmente no que se refere ao cronograma de atividades, percentual concluído e a situação atual do projeto; alguns dados devem ser, obrigatoriamente, cadastrados; 148 Linguagens de Programação II.indb 148 7/12/2006 14:00:52 Linguagens de Programação II dados repetidos não podem ser cadastrados; o sistema deve possibilitar formas de pesquisas aos projetos, participantes e integrantes de cada projeto. Voltamos a relatar que esta é uma análise bem simples sobre o tema Gerência de Projetos e, com certeza, você faria uma análise diferenciada da nossa, mas o importante aqui é o levantamento dos requisitos que deverão ser implementados. Seção 3 – Criando o modelo lógico de banco de dados Neste primeiro passo, a modelagem de dados representará os conjuntos de dados apresentados pelo levantamento de dados da seção anterior, sem se preocupar com a ferramenta de SGDB que será usada posteriormente. Veja que esta análise será dividida em: projeto; participantes; relação entre projetos e participantes. Propriedades de um projeto Com base no levantamento de dados, é preciso definir quais as propriedades que precisam ser armazenadas no banco de dados para cada projeto. É importante que o projeto possua um código de identificação interna, como uma chave primária, que não permita a repetição deste campo único. Como normalmente utilizamos um nome para identificar algo, o projeto também possuirá um nome de identificação externa, chamado de Descrição. Unidade 6 Linguagens de Programação II.indb 149 149 7/12/2006 14:00:52 Universidade do Sul de Santa Catarina Para concluir, o projeto deverá possuir as seguintes características: data de início e encerramento; situação; percentual concluído. Pois bem, convertendo estas propriedades para uma entidade de banco de dados, tem-se: FIGURA 6.1 ENTIDADE PROJETOS Não se preocupe com os comandos SQL-DDL para definição desta tabela, pois isto será feito na próxima seção, uma vez que é necessária a representação de mais duas entidades, os participantes e a relação entre projetos e participantes. Propriedades de um participante Ainda com base no levantamento de dados, você precisa definir quais as propriedades que precisam ser armazenadas no banco de dados para cada participante dos projetos. É importante que o participante possua um código de identificação interna, como uma chave primária, que não permita a repetição deste campo único. Para uma identificação mais legível e amigável, um nome para identificar cada participante também se faz necessário. Para concluir, o participante deverá possuir também uma identificação do seu cargo funcional. 150 Linguagens de Programação II.indb 150 7/12/2006 14:00:52 Linguagens de Programação II Pois bem, convertendo estas propriedades para uma entidade de banco de dados, tem-se: FIGURA 6.2 ENTIDADE PARTICIPANTE Agora, só falta a representação da relação dos projetos e de seus participantes. Para tanto, é necessária a criação de um relacionamento entre os projetos e seus participantes, a fim de se garantir a integridade dos dados, pois um projeto só pode existir se estiver cadastrado na entidade de projetos e só pode ter como integrante um participante cadastrado na entidade de participantes. Com isto, evita-se a redundância de dados (recadastramento) e garante-se a integridade dos mesmos. Veja como fica o relacionamento no modelo lógico completo: FIGURA 6.3 MODELO LÓGICO COMPLETO Unidade 6 Linguagens de Programação II.indb 151 151 7/12/2006 14:00:52 Universidade do Sul de Santa Catarina Agora sim, você já pode ver como transformar este modelo lógico em um modelo físico para o SGDB do MySQL, através dos comandos de definição de dados (SQL-DDL). Mas isso é assunto para próxima seção. Seção 4 – Modelo de dados do sistema Nesta seção, você poderá revisar os comandos de definição de dados do SQL, chamados de comandos de DDL (Data Definition Language), que compreendem os comandos: Create Database e Drop Database. Use. Create e Drop Table. Alter Table. Create Index e Drop Index. Entretanto, para esta unidade, os comandos utilizados serão o create table, drop table, create database e drop database. Para fazer uma revisão destes comandos, veja o quadro a seguir: QUADRO 2 - LISTA DE COMANDOS SQL – DDL Comando Funcionalidade Create Database <Nome_Database>; Cria um Database no MSQL Drop Database <Nome_Database>; Remove um Database no MySQL Use <Nome_DataBase> Acessa um Database no MySQL Create Table <Nome_Tabela>( Coluna1 Tipo,...,CounaN Tipo ); Cria uma tabela de banco de dados Drop Table <Nome_Tabela>; Remove uma tabela do banco de dados Alter Table <Nome_Tabela> Modify/Add Coluna Tipo; Altera as colunas de uma tabela Create Index <Nome_Indice> on Nome_Tabela(Coluna); Cria um índice para tabela Drop Index <Nome_Indice> on Tabela; Remove o índice de uma tabela 152 Linguagens de Programação II.indb 152 7/12/2006 14:00:53 Linguagens de Programação II Com base nas sintaxes apresentadas acima, já é possível você começar a criar as tabelas do modelo de dados que implementa o sistema de gerência de projetos. Criação da tabela de projetos Com base no modelo de dados lógico, apresentado na figura 3, da seção 4, o comando de criação da tabela de projetos ficará da seguinte forma: CREATE TABLE Projetos ( idProjetos INTEGER NOT NULL AUTO_INCREMENT, vDescricao VARCHAR(30) NOT NULL, dDataInicio DATE NOT NULL, dDataFinal DATE NOT NULL, nPercConcluido INTEGER UNSIGNED NOT NULL, vSituacao VARCHAR(35) NOT NULL, PRIMARY KEY(idProjetos) ); Note que o campo idProjetos, além de ser um campo chave primária (que não se repete), inteiro (Integer), também é um campo do tipo auto-incremento e, desta forma, não precisa ser cadastrado, pois seu valor é gerado de forma automática. Criação da tabela de participantes Com base no mesmo modelo de dados lógico, o comando de criação da tabela de participantes ficará da seguinte forma: CREATE TABLE Participantes ( idParticipantes INTEGER NOT NULL AUTO_INCREMENT, vNome VARCHAR(30) NOT NULL, vCargo VARCHAR(30) NOT NULL, PRIMARY KEY(idParticipantes) ); Unidade 6 Linguagens de Programação II.indb 153 153 7/12/2006 14:00:53 Universidade do Sul de Santa Catarina Note que o campo idParticipantes, além de ser um campo chave primária (que não se repete), inteiro (Integer), também é um campo do tipo auto-incremento e, desta forma, não precisa ser cadastrado, pois seu valor é gerado de forma automática. Para fechar a criação da tabela associativa Controles, é que faz a relação entre os projetos e seus participantes. Veja, a seguir, o código que cria esta tabela: CREATE TABLE Controles ( Projetos_idProjetos INTEGER NOT NULL, Participantes_idParticipantes INTEGER NOT NULL, Primary ke(Projetos_idProjetos,Participantes_idParticipantes), Foreign Key(Participantes_idParticipantes) references Participantes(idParticipantes), Foreign key(Projetos_idProjetos) references Projetos (idProjetos) ); Essa tabela possui algumas propriedades importantes, como: os campos Projetos_idProjetos e Participantes_ idParticipantes formam uma chave primária composta; o campo Projetos_idProjetos é uma chave estrangeira para tabela de projetos; o campo Participantes _id Participantes é uma chave estrangeira para tabela de participantes. Como estas tabelas serão a base das implementações que serão realizadas nas unidades que seguem, é importante que seja criado um script de SQL, que implemente todo o modelo de banco de dados, inclusive o database que conterá o banco de dados. Mas isto já é nosso próximo tema. 154 Linguagens de Programação II.indb 154 7/12/2006 14:00:53 Linguagens de Programação II Seção 5 – Criação do Script SQL do banco de dados O script SQL é um arquivo escrito em qualquer tipo de editor de texto, como, por exemplo, o Bloco de Notas do Windows. O ideal é salvar este arquivo com a extensão .sql para indicar que se trata de um script SQL. Neste arquivo, são escritos os comandos em SQL que realizam as seguintes tarefas: criação das tabelas; definição das colunas de cada tabela (campos); definição dos tipos de dados de cada coluna (campo); definição das regras de chave primária e chave estrangeira de cada tabela. O script em SQL de criação do banco de dados está diretamente relacionado aos comandos de definição de dados da linguagem SQL, que são: Create Table, Drop Table e Alter Table. O script geral, que será apresentado aqui, pode ser baixado por você na seção “Midiateca” do ambiente virtual da disciplina (EVA). Veja como ficou o script completo: #criar o database chamado livro create database if not exists livro; #entrar no database livro use livro; #remove as tabelas para recriá-las drop table if exists controles; drop table if exists participantes; drop table if exists projetos; #cria a tabela de Projetos CREATE TABLE Projetos ( idProjetos INTEGER NOT NULL AUTO_INCREMENT, vDescricao VARCHAR(30) NOT NULL, dDataInicio DATE NOT NULL, dDataFinal DATE NOT NULL, nPercConcluido INTEGER UNSIGNED NOT NULL, vSituacao VARCHAR(35) NOT NULL, PRIMARY KEY(idProjetos) ); Unidade 6 Linguagens de Programação II.indb 155 155 7/12/2006 14:00:53 Universidade do Sul de Santa Catarina #cria a tabela de Participantes CREATE TABLE Participantes ( idParticipantes INTEGER NOT NULL AUTO_INCREMENT, vNome VARCHAR(30) NOT NULL, vCargo VARCHAR(30) NOT NULL, PRIMARY KEY(idParticipantes) ); #cria a tabela de controles CREATE TABLE Controles ( Projetos_idProjetos INTEGER NOT NULL, Participantes_idParticipantes INTEGER NOT NULL, Primary key (Projetos_idProjetos,Participantes_idParticipantes), Foreign Key(Participantes_idParticipantes) references Participantes(idParticipantes), Foreign key(Projetos_idProjetos) references Projetos (idProjetos) ); #lista as tabelas criadas show tables; Bem, com esse script, você tem a modelagem do banco de dados em um formato que pode ser lido pela ferramenta de banco de dados e que será utilizado para implementação do sistema e armazenamento dos dados. Para testá-lo, basta que você crie o arquivo de script ou baixe-o da midiateca, selecione todas as linhas do script e as copie. Depois, acesse o editor de comandos do MySQL (MySQL Command Line Client) e cole as linhas no editor. Todas as linhas serão executadas automaticamente e, ao final, os nomes das tabelas criadas serão apresentadas na tela, conforme a tela a seguir: FIGURA 6.4 RESULTADO DA EXECUÇÃO DO SCRIPT 156 Linguagens de Programação II.indb 156 7/12/2006 14:00:53 Linguagens de Programação II Esta é uma entre várias etapas para se criar um software. Na próxima unidade, você aprenderá a etapa de criação das classes em Java, que farão a ligação entre este banco de dados criado e o software implementado. Até a próxima unidade! Síntese Você pôde estudar, nesta unidade, que a tarefa de desenvolver software requer muita análise por parte do profissional. A principal dificuldade é transformar um problema em uma solução computacional, que atenda às necessidades do cliente e seus usuários. As tarefas de especificação do problema possuem uma cronologia e ordem formal, a inversão destas tarefas pode resultar em mais tempo de desenvolvimento e, conseqüentemente, em maior custo. Na maioria das vezes, um sistema computacional está agregado a uma solução de banco de dados, responsável por armazenar e garantir a integridade dos mesmos. Para se chegar a um modelo de dados ideal e que atenda às necessidades do usuário é importantíssimo um levantamento de dados criterioso e organizado. A representação do modelo de dados é feita pela modelagem de entidade e relacionamentos, que é uma representação gráfica, para maior compreensão da solução que esta sendo adotada. Para transformar esta solução em uma ferramenta de banco de dados, é necessária a criação de um conjunto de comandos em SQL que construa e altere as estruturas modeladas, e este conjunto de comandos é chamado de Script. Um script pode mudar de acordo com a ferramenta computacional que se deseja adotar, por algum novo comando que seja Unidade 6 Linguagens de Programação II.indb 157 157 7/12/2006 14:00:54 Universidade do Sul de Santa Catarina necessário, porém a modelagem de entidade e relacionamento é única, independente da ferramenta computacional e é a principal referência para o sistema que será implementado. Atividades de auto-avaliação Efetue as atividades de auto-avaliação e, a seguir, acompanhe as respostas e comentários a respeito. Para melhor aproveitamento do seu estudo, realize a conferência de suas respostas somente depois de fazer as atividades propostas. 1) Ao se modelar um problema, você acha que o usuário realmente passa todos os dados necessários ou alguns deles são omitidos, com medo que o sistema desenvolvido venha a substituí-lo no serviço? 2) Quando se desenvolve um produto, como uma cadeira, uma casa, etc., durante o processo de criação é possível apresentá-lo ao cliente, para seu acompanhamento. Porém, no caso de desenvolvimento de softwares não há um produto palpável para ser apresentado. Como agir em uma situação como esta? Saiba mais Para aprofundar as questões abordadas nesta unidade, você poderá pesquisar em: DATE, C. J. Bancos de dados: fundamentos. Rio de Janeiro: Campus, 1985. DATE, C. J. Introdução ao sistema de banco de dados. 8 ed. Rio de Janeiro: Campus, 1990. SOARES, Walace. MySQL: conceitos e aplicações. São Paulo: Erica, 2002. 158 Linguagens de Programação II.indb 158 7/12/2006 14:00:54 UNIDADE 7 Conectando o Java ao Banco de Dados 7 Objetivos de aprendizagem Entender o processo de conexão entre uma linguagem de programação e uma ferramenta de banco de dados. Compreender o funcionamento do driver JDBC. Instalar e configurar o driver de conexão do Java para MySQL. Criar uma classe de conexão ao banco de dados MySQL. Seções de estudo Seção 1 Driver de conexão Seção 2 Driver de conexão JDBC Seção 3 Criando uma classe de conexão ao MySQL Linguagens de Programação II.indb 159 7/12/2006 14:00:54 Universidade do Sul de Santa Catarina Para início de conversa Nas unidades anteriores, você pôde conhecer o modelo de dados que será usado para criação do sistema de gerência de projetos. A partir de agora, é necessário que você compreenda como fazer uma aplicação escrita em Java e se conectar a um banco de dados, de forma segura e confiável. Sendo assim, seja bem-vindo ao mundo dos drivers de conexão! Seção 1 – Driver de conexão Uma funcionalidade essencial em qualquer software é a sua capacidade de se comunicar com um banco de dados, independentemente da linguagem de programação utilizada para implementação. A linguagem de programação possui uma sintaxe própria e as ferramentas de banco de dados funcionam baseadas na linguagem SQL – o que significa que estas duas tecnologias não conseguem conversar entre si. É como se duas pessoas de idiomas diferentes começassem a conversar, sem que um entendesse o outro. Seria um problema, não acha? Sendo assim, é necessário que um interpretador faça o papel de conversão entre eles, de forma que os dois possam se comunicar. Veja a imagem a seguir: Software Driver Banco de dados FIGURA 7. 1 - FUNCIONAMENTO DE UM DRIVER 160 Linguagens de Programação II.indb 160 7/12/2006 14:00:54 Linguagens de Programação II No caso da computação, este interpretador recebe o nome de Driver de Conexão. Como cada ferramenta de banco de dados possui particularidades no seu funcionamento, normalmente o driver de conexão é distribuído pelo próprio fabricante do banco de dados. No caso do sistema operacional Windows, há um conjunto de drivers para conectividade a banco de dados, chamado de Open DataBase Connectivity (Padrão Aberto de Conectividade), ou simplesmente ODBC. A maioria dos drivers de conexão disponíveis no ODBC é para bancos de dados antigos, muitos até deixaram de ser usados, como: Dbase, Clipper. Sendo assim, para a maioria dos bancos de dados atuais é necessário que o usuário instale no seu computador o driver específico para a ferramenta que ele está utilizando. No caso do projeto de gerência de projetos, o driver deve ser do banco de dados MySQL e voltado para plataforma Java... mas isto é assunto para a seção a seguir! Seção 2 – Driver de conexão JDBC No Java, os drivers ODBC recebem o nome de JDBC, ou seja, driver ODBC específico para Java. O driver JDBC é o driver ODBC que permite a conexão entre um banco de dados e o programa escrito em Java. Seria o intérprete entre um sistema desenvolvido em Java e um banco de dados, possibilitando a comunicação entre eles. Programa em Java JDBC Banco de dados FIGURA 7.2 - PAPEL DO DRIVER DE CONEXÃO JDBC Unidade 7 Linguagens de Programação II.indb 161 161 7/12/2006 14:00:54 Universidade do Sul de Santa Catarina O uso do JDBC apresenta algumas vantagens para a aplicação Java: maior portabilidade, facilidade de configuração e padronização. Como baixar e instalar um driver JDBC? Com base na ferramenta que será utilizada como banco de dados, acesse o site do fabricante e procure, na área de download, pelo driver de conexão JDBC. Para facilitar, acesse o link: <http:// dev.mysql.com/downloads/connector/j/3.1.html>, para baixar o JDBC para MySQL. Esse driver será usado por você para conexão do software. Veja o site de download deste driver de conexão: FIGURA 7.3 - SITE DE DOWNLOAD DO DRIVER DE CONEXÃO DO MYSQL Para baixar o arquivo, clique no link Pick a Mirror, AO LADO DA OPÇÃO ZIP, conforme a imagem a seguir: 162 Linguagens de Programação II.indb 162 7/12/2006 14:00:55 Linguagens de Programação II FIGURA 7.4 - LINK PARA O DRIVER DE CONEXÃO DO MYSQL Na página que se abre, procure um Mirror do Brasil e clique na palavra Http, conforme a imagem a seguir: FIGURA 7.5 - LINK PARA INICIAR O DOWNLOAD DO ARQUIVO Na janela que se abre, clique no botão salvar e direcione o salvamento do arquivo para um diretório de sua escolha. FIGURA 7.6 - JANELA DE SALVAMENTO DO ARQUIVO Unidade 7 Linguagens de Programação II.indb 163 163 7/12/2006 14:00:55 Universidade do Sul de Santa Catarina Este arquivo não precisa ser instalado, apenas descompacte-o conforme os passos a seguir: 1) Clique no arquivo baixado anteriormente com o driver JODBC; 2) Descompacte-o para uma pasta de sua preferência, pode ser a mesma pasta na qual você o salvou durante o download do arquivo; 3) Na pasta será criado um arquivo chamado “mysqlconnector-java-5.0.3-bin.jar”.Este nome pode mudar dependendo da versão que você baixou. 4) Copie este arquivo para pasta \jre\lib\ext . Esta pasta fica dentro do diretório em que você instalou o Java na sua máquina. Algo como: C:\Arquivos de Programas\Java\jdkX. Y.Z_00\jre\lib\ext. Pronto, o driver está pronto para ser usado. Seção 3 – Criando uma classe em Java para conexão com Banco de Dados A conexão com um banco de dados, através da linguagem Java pode ser dividida em três processos distintos: conectar ao banco de dados; executar comandos com recuperação de dados – Select; executar comandos sem recuperação de dados – Insert, Update e Delete. Vale destacar que, se o primeiro processo não for efetivado com sucesso, os demais não podem ser realizados. 164 Linguagens de Programação II.indb 164 7/12/2006 14:00:55 Linguagens de Programação II Veja o diagrama a seguir: Conectar ao Banco de Dados CONECTOU ? não Mensagem de ERRO Encerra o programa sim Usuário tem acesso Banco de Dados FIGURA 7.7 - FORMA DE ACESSO AO UM SOFTWARE COM CONEXÃO AO BANCO DE DADOS A conexão com o banco de dados se dá pela conexão JDBC, utilizando a classe chamada DriverManager, que poderia ser traduzido para administrador do driver. Esta classe pertence ao pacote java.sql e serve para: criar a conexão com o banco de dados; administrar o driver JDBC usado na conexão; controlar o acesso ao banco de dados via Login; controlar a troca de informação entre o driver e a ferramenta de banco de dados. Como o DriverManager pertence ao pacote Java.sql, sempre que você for utilizá-lo deverá incluir a linha import java.sql.* no código fonte da sua classe, pois este não é um pacote nativo do Java. Unidade 7 Linguagens de Programação II.indb 165 165 7/12/2006 14:00:55 Universidade do Sul de Santa Catarina Lembre-se: a linguagem Java é Case Sensitive, ou seja, maiúsculo é diferente de minúsculo. Sendo assim, a classe DriverManager é reconhecida, já a classe drivermanager será um comando não reconhecido pela linguagem. Como usar a classe DriverManager? A sintaxe do uso desta classe é bem simples, assim como a finalidade dela é especificamente a conexão com o banco de dados, os seus atributos se referem a dados como: nome do servidor de acesso, a porta de acesso (3306 – mysql) e o nome do database; nome do usuário; senha de acesso ao banco de dados. Para que a classe DriverManager receba estes valores, é necessária a utilização do método getConnection(), que será melhor detalhado a seguir. Assim, a sintaxe de uso do DriverManager é: DriverManager.getConnection(URL, usuário, senha); Onde: URL: String; Nome do Usuário: String; Senha: String; 166 Linguagens de Programação II.indb 166 7/12/2006 14:00:56 Linguagens de Programação II Os nomes do usuário e da senha de acesso seguem as regras da definição do banco de dados. No caso do banco de dados MySQL instalado por você, será a mesma senha e usuário que você usa para se logar ao MySQL. O método getConnection() retorna sempre um atributo do tipo Connection, que pode ser fechado por meio do método close(). A partir do momento que o banco de dados foi fechado, ele não pode mais ser manipulado, a não ser que uma nova conexão seja aberta através do getConnection(). Sempre que você encerrar a aplicação, feche o banco de dados. Os comandos do getConnection() são sempre os mesmos, o que pode mudar são os parâmetros de nome da fonte, usuário e senha. Sendo assim, a conexão com banco de dados poderia ser representada por uma classe como: FIGURA 7.8 - DIAGRAMA DA CLASSE DE CONEXÃO COM BANCO DE DADOS EM JAVA O que significa cada um destes itens? Unidade 7 Linguagens de Programação II.indb 167 167 7/12/2006 14:00:56 Universidade do Sul de Santa Catarina Bem, cada um destes itens possui uma característica dentro da classe de conexão, que é: Ususário – nome do usuário que se conectará ao MySQL; Senha – senha de acesso ao MySQL; Servidor – servidor de onde o MySQL será acessado; DataBase – banco de dados que será acessado; Con – classe do tipo Connection do próprio Java que faz a conexão com o banco de dados; Conectado – campo lógico que indica se a conexão foi realizada; Dados – classe do tipo ResultSet, do Java, que armazena os resultados de um comando “Select”; Conexao() – método que instancia a classe Conexão; Conectar() – método que faz a conexão com o banco de dados; FecharConexao() – método que fecha a conexão com o banco de dados; ExpressaoSQL – método que executa um comando de SQL. Agora que a estrutura da classe já é conhecida, o próximo passo é criá-la através dos comandos em Java. Abra o seu editor de Java preferido, crie um projeto com nome “classes_livro”. Crie uma nova classe chamada Conexao.java para este projeto e edite o seguinte código-fonte: import javax.swing.JOptionPane; import java.sql.*; public class Conexao { //Atributos da Classes private String Usuario,Senha,Servidor,DataBase; private Connection Con; private boolean Conectado; private ResultSet Dados; 168 Linguagens de Programação II.indb 168 7/12/2006 14:00:56 Linguagens de Programação II //Construtor da Classe public Conexao(){ setSenha(“”); setUsuario(“”); setServidor(“”); setConectado(false); setCon(null); setDados(null); setDataBase(“”); } public Conexao(String SERV,String DB,String USU,String SENHA){ setSenha(SENHA); setUsuario(USU); setServidor(SERV); setDataBase(DB); setConectado(false); setCon(null); setDados(null); } //Modificadores public void setCon(Connection con) {Con = con;} public void setConectado(boolean conectado) {Conectado = conectado;} public void setSenha(String senha) {Senha = senha;} public void setUsuario(String usuario) {Usuario = usuario;} public void setServidor(String servidor) {Servidor = servidor;} public void setDados(ResultSet dados) {Dados = dados;} public void setDataBase(String DB) {DataBase = DB;} //Recuperadores public String getUsuario() {return Usuario;} public String getSenha() {return Senha;} public boolean getConectado() {return Conectado;} public Connection getCon() {return Con;} public String getServidor() {return Servidor;} public ResultSet getDados() {return Dados;} public String getDataBase() {return DataBase;} public void Conectar() { try{ Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://”+getServidor()+”:3306”+”/”+getDataBase(); setCon(DriverManager.getConnection(URL,getUsuario(),getSenha())); setConectado(true); } catch (Exception e){ JOptionPane.showMessageDialog(null,”Conexão não foi realizada!”,””, JOptionPane. WARNING_MESSAGE); JOptionPane.showMessageDialog(null,”Erro :”+e.getMessage(),””, JOptionPane. WARNING_MESSAGE); setConectado(false); return; Unidade 7 Linguagens de Programação II.indb 169 169 7/12/2006 14:00:56 Universidade do Sul de Santa Catarina } JOptionPane.showMessageDialog(null,”Conexão realizada com Sucesso!”,””, JOptionPane. WARNING_MESSAGE); } public void FecharConexao(){ try{ if(getConectado()) getCon().close(); } catch (Exception e ){ JOptionPane.showMessageDialog(null,”Conexão não foi fechada!”,””, JOptionPane. WARNING_MESSAGE); JOptionPane.showMessageDialog(null,”Erro :”+e.getMessage(),””, JOptionPane. WARNING_MESSAGE); } } public void ExpressaoSQL(String Comando){ if(getConectado()){ try{ Statement st = getCon().createStatement(); if(Comando.toUpperCase().indexOf(“SELECT”)!= -1) setDados(st.executeQuery(Comando)); else{ setDados(null); st.executeUpdate(Comando); if(Comando.toUpperCase().indexOf(“UPDATE”)!= -1) JOptionPane.showMessageDialog(null,”Dados Atualizados!”,””, JOptionPane. WARNING_MESSAGE); else if(Comando.toUpperCase().indexOf(“DELETE”)!= -1) JOptionPane.showMessageDialog(null,”Dados Removidos!”,””, JOptionPane. WARNING_MESSAGE); else if(Comando.toUpperCase().indexOf(“INSERT”)!= -1) JOptionPane.showMessageDialog(null,”Dados Inseridos!”,””, JOptionPane. WARNING_MESSAGE); } } catch(SQLException sqle){ JOptionPane.showMessageDialog(null,”SQL Inválido!”,””, JOptionPane. WARNING_MESSAGE); JOptionPane.showMessageDialog(null,”Erro :”+sqle.getMessage(),””, JOptionPane. WARNING_MESSAGE); } } } } 170 Linguagens de Programação II.indb 170 7/12/2006 14:00:56 Linguagens de Programação II Compile a classe para que, mais à frente, você possa criar uma classe de teste para verificar a sua funcionalidade. Para detalhar o código, utilizaremos a tabela a seguir: Linha de Comando Funcionalidade import javax.swing.*; Pacote importado para JOptionPane import java.sql.*; Pacote Java para manipulação de banco de dados. class Conexao Nome da classe criada deve ter o mesmo nome do arquivo em Java. private String Usuario,Senha, Servidor,DataBase; private Connection Con; private boolean Conectado; private ResultSet Dados; Atributos da classe são sempre private. public Conexao(String SERV,String DB,String USU,String SENHA) Construtor da classe Conexao, recebendo como parâmetro os valores do servidor, usuário e senha. String URL = “jdbc:mysql:// ”+getServidor()+”:3306”+”/”+getDataBase(); O nome da URL em Java, é identificada como “jdbc: mysql:” e, em seguida, o servidor, a porta de conexão e o nome do banco de dados que se deseja acessar. Class.forName(“com.mysql.jdbc.Driver”); Carrega o driver que será usado para conexão com o Java. Neste caso, será uma conexão via JDBC. DriverManager.getConnection(URL, getUsuario(),getSenha()) Tenta fazer a conexão com o banco de dados a partir da URL, usuário e senha fornecidos. setCon(DriverManager.getConnection( URL,getUsuario(),getSenha())); O método setCon () armazena no atributo Con o resultado da execução do comando getConnection. try{ } catch(Exception e){ } Toda a operação de banco de dados em Java, obrigatoriamente, deve ser protegida com tratamento de exceção try.. catch. getConexao().close(); Fecha o banco de dados. Por ser uma operação de banco de dados, deve ser protegida por try e catch. ExpressaoSQL(String Comando) Executa um comando em SQL e guarda o resultado do comando no atributo Dados, do tipo ReultSet. Unidade 7 Linguagens de Programação II.indb 171 171 7/12/2006 14:00:57 Universidade do Sul de Santa Catarina Qualquer dúvida, baixe da “Midiateca” a fonte desta classe para ganhar tempo. Para testar esta classe, crie uma nova classe no seu editor JAVA, com o nome de testeConexao, conforme o modelo a seguir: public class testeConexao{ public static void main(String args[]){ Conexao C = new Conexao(“localhost”,”nome do banco”,”usuario”,”senha”); C.Conectar(); C.FecharConexao(); } } Lembre-se de mudar o usuário e a senha para a forma pela qual você conecta o MySQL na sua máquina, com a sua senha e o seu nome de usuário. É importante que você tenha copiado o driver JDBC para o diretório \jre\lib\ext, caso contrário, a aplicação em Java não conseguirá se conectar ao MySQL. Se tudo correu bem, o resultado da execução será: FIGURA 7.9 - RESULTADO DA EXECUÇÃO DA CLASSE TESTECONEXAO O próximo passo é realizar as operações de inserção, exclusão e atualização das tabelas do banco de dados. 172 Linguagens de Programação II.indb 172 7/12/2006 14:00:57 Linguagens de Programação II Síntese Nesta unidade, você pode revisar alguns conceitos da programação em Java, principalmente na estrutura de uma classe, assim como a mesma pode ser instanciada e usada. Junto a comandos que você já conhecia e que são essenciais para programação em Java, algumas novas classes foram apresentadas a você, como as DriverManager, Connection Statement e ResultSet. No momento, estas estruturas podem parecer complexas, mas lembre-se que se trata de um assunto novo, recém abordado. À medida que você for interagindo com estas classes, inclusive nas unidades que se seguem, o uso se tornará fácil e direto. Atividades de auto-avaliação 1) Qual a finalidade do tratamento de exceção? 2) A definição das regras de conexão com banco de dados através de classes é uma garantia de funcionamento dentro do esperado? Unidade 7 Linguagens de Programação II.indb 173 173 7/12/2006 14:00:57 Universidade do Sul de Santa Catarina Saiba mais Para aprofundar as questões abordadas nesta unidade, você poderá pesquisar em: THOMPSON, Marco Aurélio. Java 2 & banco de dados. São Paulo, Érica: 2002. DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. SIERRA, Kathy; BATES, Bert. Java use a cabeça. Alta Books: 2005. 174 Linguagens de Programação II.indb 174 7/12/2006 14:00:57 UNIDADE 8 Criando as Classes de Representação 8 Objetivos de aprendizagem Aplicar as técnicas da Programação Orientada a Objetos do Java. Criar um conjunto de classes que representem as tabelas do banco de dados. Criar as regras de validação de entrada de dados das tabelas do banco de dados. Seções de estudo Seção 1 Estrutura da Classe de Projetos Seção 2 Estrutura da Classe de Participantes Seção 3 Estrutura da Classe de Controles Linguagens de Programação II.indb 175 7/12/2006 14:00:57 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você atuará como um desenvolvedor de soluções, criando um conjunto de classes em Java que permita a validação dos dados das tabelas do banco de dados, criado para o sistema de gerenciamento de projetos. Cada tabela do modelo de dados físicos possui um conjunto particular de propriedades que deverão ser validadas através destas classes, como entrada de valores inválidos, valores nulos ou, até mesmo, valores repetidos. A finalidade de se implementar estas regras nestas classes é de garantir que as tabelas do banco de dados estarão trabalhando com dados confiáveis e íntegros. Portanto, Java já! Seção 1 – Estrutura da Classe de Projetos Nas unidades anteriores, você pôde criar a tabela do banco de dados que deverá representar os dados de cada projeto cadastrado no sistema. Entretanto, esta tabela não possui nenhum tipo de consistência com relação aos valores que poderão ser inseridos, listados ou removidos. Além disso, tal tabela está formalizada dentro de uma outra ferramenta, que é o MySQL, o qual, por sua vez, pode ser conectado através do driver JDBC. Com base nisto, nesta seção, você agora verá como criar uma classe em Java que faça a integração em aplicativo (software) e ferramenta de banco de dados (MySQL) de forma a garantir o total controle das atividades executadas pelo sistema, evitando-se que processos inesperados sejam executados ou valores inválidos sejam inseridos nas tabelas. 176 Linguagens de Programação II.indb 176 7/12/2006 14:00:57 Linguagens de Programação II Para começar, você criará uma classe para representar a tabela Projetos dentro do Java. Mas antes, seria bom revisar a estrutura da tabela Projetos. Veja: FIGURA 8.1 – TABELA PROJETOS Esta tabela possui uma estrutura bem simples, com campos numéricos, alfa-numéricos e do tipo data. Você precisa criar, como ponto principal, uma estrutura que permita a validação dos dados inseridos na tabela, bem como a apresentação dos dados na tela. Veja, a seguir, a estrutura da classe Projetos que implementa estas regras. O código completo pode ser baixado na midiateca. import java.util.*; import java.text.*; import javax.swing.JOptionPane; public class Projetos { //Atributos da Classe private int idProjeto; private String vDescricao; private String dDataInicio,dDataFinal; private int nPercentual; private String vSituacao; private boolean bConsistencia; public Projetos(){ setIdProjeto(0); setDescricao(“”); setDataInicio(“01/01/2000”); setDataFinal(“01/01/2000”); setPercentual(0); setSituacao(“Em aberto”); setConsistencia(false); } Unidade 8 Linguagens de Programação II.indb 177 177 7/12/2006 14:00:57 Universidade do Sul de Santa Catarina //Modificadores Método setIdProjeto() - grava o public void setIdProjeto(int idProjeto){ código do Projeto, desde que o if (idProjeto >= 0) valor seja positivo e maior que zero. this.idProjeto = idProjeto; else{ this.idProjeto = -1; JOptionPane.showMessageDialog(null,”Código Incorreto.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } Armazena a situação da inserção. Caso setConsistencia(true); algum problema ocorra, a consistência } estará valendo como falso. public void setDescricao(String descricao){ if (descricao.length() > 0) Verifica se o valor da descrição foi vDescricao = descricao; informado, caso contrário, grava o else{ vDescricao = “Anônimo”; valor “Anônimo”. setConsistencia(false); return; } setConsistencia(true); } public void setDataInicio(String dataInicio){ if(DataCorreta(dataInicio)) dDataInicio = dataInicio; else{ DateFormat df = DateFormat.getDateInstance(); dDataInicio = df.format(new Date()); } } Verifica se a data informada está correta, caso contrário, grava a data atual. public void setDataFinal(String dataFinal){ if(DataCorreta(dataFinal)) dDataFinal = dataFinal; else{ DateFormat df = DateFormat.getDateInstance(); dDataFinal = df.format(new Date()); } } public void setPercentual(int percentual){ Verifica se o percentual if(percentual >=0) nPercentual = percentual; informado é positivo e maior else ou igual a 0. { nPercentual = 0; JOptionPane.showMessageDialog(null,”Percentual Inválido.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } 178 Linguagens de Programação II.indb 178 7/12/2006 14:00:58 Linguagens de Programação II setConsistencia(true); } public void setSituacao(String situacao) { Verifica se o valor da situação if (SituacaoCorreta(situacao)) vSituacao = situacao; foi informado, caso contrário, else{ grava o valor “Em aberto”. vSituacao = “Em aberto”; JOptionPane.showMessageDialog(null,”Opção Inválida.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } setConsistencia(true); } public void setConsistencia(boolean consistencia){ bConsistencia = consistencia; } //Recuperadores public String getDataFinal() {return dDataFinal;} public String getDataInicio() {return dDataInicio;} public int getIdProjeto() {return idProjeto;} public int getPercentual() {return nPercentual;} public String getDescricao() {return vDescricao;} public String getSituacao() {return vSituacao;} public boolean getConsistencia() {return bConsistencia;} //---- Regras de Negócio // Verifica se a data informada esta correta private boolean DataCorreta(String Data){ try { SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yyyy”); sdf.setLenient false); Date d = sdf.parse(Data); } catch(ParseException e) { JOptionPane.showMessageDialog(null,”Formato incorreto “ + Data,””,JOptionPane. WARNING_MESSAGE); return false; } return true; } Unidade 8 Linguagens de Programação II.indb 179 179 7/12/2006 14:00:58 Universidade do Sul de Santa Catarina // Verifica se a situação esta dentro das opções válidas private boolean SituacaoCorreta(String opcao){ Vector opcoes = new Vector(); opcoes.add(“FINALIZADO”); opcoes.add(“EM ABERTO”); opcoes.add(“EM EXECUÇÃO”); return opcoes.contains(opcao.toUpperCase()); } Verifica se a situação é uma das possíveis. // Realiza o cadastro dos dados do Projeto public void LeiaDados(){ setIdProjeto(Integer.parseInt(JOptionPane.showInputDialog(“Código do Projeto”))); if (getConsistencia()) setDescricao(JOptionPane.showInputDialog(“Descrição do Projeto”)); if (getConsistencia()) setDataInicio(JOptionPane.showInputDialog(“Data de Início do Projeto”)); if (getConsistencia()) setDataFinal(JOptionPane.showInputDialog(“Data de Encerramento do Projeto”)); if (getConsistencia()) setPercentual(Integer.parseInt(JOptionPane.showInputDialog(“Percentual do Projeto”))); if (getConsistencia()) setSituacao(JOptionPane.showInputDialog(“Situação do Projeto”)); if (!getConsistencia()) JOptionPane.showMessageDialog(null,”Os dados não foram lidos!”,””, JOptionPane. WARNING_MESSAGE); } //Realiza o cadastro dos dados, exceto o código do Projeto, que é auto-incremento public void LeiaDados(boolean AUTO){ setDescricao(JOptionPane.showInputDialog(“Descrição do Projeto”)); if (getConsistencia()) setDataInicio(JOptionPane.showInputDialog(“Data de Início do Projeto”)); if (getConsistencia()) setDataFinal(JOptionPane.showInputDialog(“Data de Encerramento do Projeto”)); if (getConsistencia()) setPercentual(Integer.parseInt(JOptionPane.showInputDialog(“Percentual do Projeto”))); if (getConsistencia()) setSituacao(JOptionPane.showInputDialog(“Situação do Projeto”)); if (!getConsistencia()) JOptionPane.showMessageDialog(null,”Os dados não foram lidos!”,””, JOptionPane. WARNING_MESSAGE); } // Apresenta os dados cadastrados no Projeto public void ShowDados(){ String Saida = “Projeto :”+getIdProjeto()+ “\n Descricao :”+getDescricao()+ “\n Iniciado em :”+getDataInicio()+ “\n Encerrado em:”+getDataFinal()+ “\n Concluídos :”+ getPercentual()+”%” + “\n Situação :”+getSituacao(); JOptionPane.showMessageDialog(null,Saida); } 180 Linguagens de Programação II.indb 180 7/12/2006 14:00:58 Linguagens de Programação II public Vector getCampos(){ Vector Campos = new Vector(); Campos.add(“idProjetos”); Campos.add(“vDescricao”); Campos.add(“dDataInicio”); Campos.add(“dDataFinal”); Campos.add(“nPercConcluido”); Campos.add(“vSituacao”); return Campos; } Retorna um Vector com os nomes dos campos da tabela Projetos. } No método LeiaDados() foi implementado uma sobrecarga, sendo que, se este método for chamado com o parâmetro “booleano”, não será solicitado o código do projeto por se tratar de um campo de auto-incremento. Caso haja necessidade da solicitação de todos os dados, inclusive do código do projeto, a chamada do método LeiaDados() será sem parâmetros. Todo o processo de entrada de dados é validado pelo método getConsistencia(). Se este método retornar um false, todo o processo de inserção é abortado, para evitar o cadastramento de dados inválidos. Veja que a classe Projetos se torna um tanto complexa. Porém, as regras de validação estão na classe e não no banco de dados MySQL, o que evitará que o banco de dados seja executado em demasia, uma vez que a validação dos dados já foi realizada antes que o mesmo receba os valores. Com isso, tira-se do SGDB uma carga de processamento alto, que é responsável por tratar os valores inseridos nas tabelas. Esta mesma metodologia será implantada nas demais classes de representação do banco de dados. Unidade 8 Linguagens de Programação II.indb 181 181 7/12/2006 14:00:58 Universidade do Sul de Santa Catarina Seção 2 – Estrutura da Classe de Participantes Nesta seção, você continuará a criação das classes de representação. Começamos pela classe Participantes que representará a seguinte estrutura de tabela: FIGURA 8.2 – TABELA PARTICIPANTES Esta tabela possui uma estrutura bem simples, com campos numéricos e alfa-numéricos. Nosso objetivo é criar uma estrutura que permita a validação dos dados manipulados por esta classe. Veja, a seguir, a estrutura da classe Participantes: import java.util.*; import javax.swing.JOptionPane; public class Participantes { //Atributos da Classe private int idParticipante; private String vNome; private String vCargo; private boolean bConsistencia; public Participantes(){ setIdParticipante(1); setNome(“”); setCargo(“Gerente”); setConsistencia(false); } //Modificadores public void setIdParticipante(int idParticipante){ if (idParticipante > 0) this.idParticipante = idParticipante; else{ this.idParticipante = 1; JOptionPane.showMessageDialog(null,”Código Incorreto.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } 182 Linguagens de Programação II.indb 182 7/12/2006 14:00:58 Linguagens de Programação II setConsistencia(true); } public void setNome(String nome){ if (nome.length() > 0) vNome = nome; else{ vNome = “Anônimo”; setConsistencia(false); return; } setConsistencia(true); } public void setCargo(String cargo) { if (CargoCorreto(cargo)) vCargo = cargo; else{ vCargo = “Inválido”; JOptionPane.showMessageDialog(null,”Cargo Inválido.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } setConsistencia(true); } public void setConsistencia(boolean consistencia){ bConsistencia = consistencia; } //Recuperadores public String getCargo() {return vCargo;} public String getNome() {return vNome;} public int getIdParticipante() {return this.idParticipante;} public boolean getConsistencia() {return bConsistencia;} //---- Regras de Negócio // Verifica se a situação esta dentro das opções válidas private boolean CargoCorreto(String cargo){ Vector cargos = new Vector(); cargos.add(“GERENTE”); cargos.add(“PROGRAMADOR”); cargos.add(“ANALISTA DE SISTEMAS”); cargos.add(“DBA”); return cargos.contains(cargo.toUpperCase()); } // Realiza o cadastro dos dados do Projeto public void LeiaDados(){ Unidade 8 Linguagens de Programação II.indb 183 183 7/12/2006 14:00:58 Universidade do Sul de Santa Catarina setIdParticipante(Integer.parseInt(JOptionPane.showInputDialog(“Código do Participante”))); if (getConsistencia()) setNome(JOptionPane.showInputDialog(“Nome”)); if (getConsistencia()) setCargo(JOptionPane.showInputDialog(“cargo”)); if (!getConsistencia()) JOptionPane.showMessageDialog(null,”Os dados não foram lidos!”,””, JOptionPane. WARNING_MESSAGE); } public void LeiaDados(boolean AUTO){ setNome(JOptionPane.showInputDialog(“Nome”)); if (getConsistencia()) setCargo(JOptionPane.showInputDialog(“cargo”)); if (!getConsistencia()) JOptionPane.showMessageDialog(null,”Os dados não foram lidos!”,””, JOptionPane. WARNING_MESSAGE); } // Apresenta os dados cadastrados no Projeto public void ShowDados(){ String Saida = “Projetista :”+getIdParticipante()+ “\n Nome :”+getNome()+ “\n Cargo :”+getCargo(); JOptionPane.showMessageDialog(null,Saida); } public Vector getCampos(){ Vector Campos = new Vector(); Campos.add(“idParticipantes”); Campos.add(“vNome”); Campos.add(“vCargo”); return Campos; } } No método LeiaDados(), foi implementada uma sobrecarga para controlar a inserção do código do participante, que é um campo auto-incremento. Todo o processo de entrada de dados continua sendo validado por um método chamado getConsistencia(). Se este método retornar um false, todo o processo de inserção é abortado, para evitar o cadastramento de dados inválidos. Para finalizar as classes de representação, falta apenas a classe Controle, que é a mais simples das três. Vamos lá! 184 Linguagens de Programação II.indb 184 7/12/2006 14:00:59 Linguagens de Programação II Seção 3 – Estrutura da Classe de Controles Nesta seção, você terá acesso ao código fonte da última classe de representação. A classe Controles representará a seguinte estrutura de tabela: FIGURA 8.3 – TABELA CONTROLES Esta tabela possui uma estrutura bem simples, com dois campos numéricos. O objetivo aqui é criar uma estrutura que represente a ligação entre os projetos e os seus participantes. Veja, a seguir, a estrutura da classe Controles: import javax.swing.JOptionPane; import java.util.*; public class Controles { private int idProjeto; private int idParticipante; private boolean bConsistencia; public Controles(){ setIdProjeto(1); setIdParticipante(1); setConsistencia(false); } public void setIdProjeto(int idProjeto){ if (idProjeto > 0) this.idProjeto = idProjeto; else{ this.idProjeto = 1; JOptionPane.showMessageDialog(null,”Código Incorreto.”, “”,JOptionPane.WARNING_MESSAGE); setConsistencia(false); return; } Unidade 8 Linguagens de Programação II.indb 185 185 7/12/2006 14:00:59 Universidade do Sul de Santa Catarina setConsistencia(true); } public void setIdParticipante(int idParticipante){ if (idParticipante > 0) this.idParticipante = idParticipante; else{ this.idParticipante = 1; JOptionPane.showMessageDialog(null,”Código Incorreto.”, “”,JOptionPane. WARNING_MESSAGE); setConsistencia(false); return; } setConsistencia(true); } public void setConsistencia(boolean consistencia){ bConsistencia = consistencia; } //Recuperadores public int getIdProjeto() {return this.idProjeto;} public int getIdParticipante() {return this.idParticipante;} public boolean getConsistencia() {return bConsistencia;} public Vector getCampos(){ Vector Campos = new Vector(); Campos.add(“Projetos_idProjetos”); Campos.add(“Participantes_idParticipantes”); return Campos; } } Veja que, deste modo, as classes de representação das tabelas do modelo de banco de dados estão prontas. Agora, é hora de criar uma especialização destas classes de forma que seja possível a execução dos comandos em SQL. O primeiro passo será criar a classe de manipulação de dados da classe Projetos, mas isto é assunto para próxima unidade. Até lá! 186 Linguagens de Programação II.indb 186 7/12/2006 14:00:59 Linguagens de Programação II Síntese Nesta unidade você pôde revisar alguns conceitos da programação orientada a objetos, implementados em Java, como: Métodos construtores das classes, os métodos modificadores, ou simplesmente “sets” e os métodos recuperadores, ou “gets”. O principal objetivo do método construtor é inicializar os atributos das classes. Os métodos modificadores permitem a alteração das propriedades de uma classe e os recuperadores permitem que os dados de uma classe possam ser visualizados por um processo externo à classe. Para finalizar é importante que se tenha em mente que os atributos das classes são sempre privados e os métodos públicos, de forma a garantir o total controle sobre os processos que uma classe possa executar. Atividades de auto-avaliação Efetue as atividades de auto-avaliação e, a seguir, acompanhe as respostas e comentários a respeito. Para melhor aproveitamento do seu estudo, realize a conferência de suas respostas somente depois de fazer as atividades propostas. Leia com atenção os enunciados e realize, a seguir, as atividades: 1) Uma classe de conexão de banco de dados em Java pode ser implementada de forma a atender qualquer tipo de banco de dados? Unidade 8 Linguagens de Programação II.indb 187 187 7/12/2006 14:00:59 Universidade do Sul de Santa Catarina Saiba mais Aprofunde os conteúdos estudados nesta unidade ao consultar as seguintes referências: HORSTMANN, Cay S. Big Java. Porto Alegre: Artmed Bookman: 2004. THOMPSON, Marco Aurélio. Java 2 & banco de dados. São Paulo, Érica: 2002. 188 Linguagens de Programação II.indb 188 7/12/2006 14:00:59 UNIDADE 9 Criando as Classes de Controle 9 Objetivos de aprendizagem Criar um conjunto de classes que permita a execução de comandos em SQL. Implementar uma classe com conexão a banco de dados e manipulação de dados da tabela de projetos. Colocar em prática a noção de abstração em programação orientada a objetos. Seções de estudo Seção 1 Estrutura da Classe de Manipulação de Projetos Seção 2 Representação das Principais Funcionalidades Seção 3 Código fontes da Classe de Manipulação dos Projetos Seção 4 Testando a Classe de Manipulação dos Projetos Seção 5 Estrutura das demais classes Linguagens de Programação II.indb 189 7/12/2006 14:00:59 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade, você criará uma nova classe com a composição das já vistas anteriormente, permitindo a atualização de dados da tabela de projetos. A classe de regras de banco de dados permitirá a execução de um conjunto de comandos em SQL, que, por sua vez, permite a inserção, atualização e remoção de dados. A finalidade de se implementar estas regras é tornar o processo de manipulação de banco de dados o mais abstrato possível para quem usa as classes e os métodos implementados. Além, é claro, da padronização das funcionalidades implementadas. Seção 1 – Estrutura da Classe de Manipulação de Projetos A classe de manipulação de dados está voltada aos comandos em SQL, que permite o gerenciamento dos dados dos projetos cadastrados. Basicamente, esta classe deve admitir: Inserção de dados. Remoção de dados. Atualização de dados. Listagem dos dados cadastrados. A inserção de dados realiza o cadastramento de todos os dados da tabela Projetos, com base na estrutura da classe Projetos e da tabela de dados Projetos. 190 Linguagens de Programação II.indb 190 7/12/2006 14:00:59 Linguagens de Programação II A remoção dos dados pode ser feita a partir de um código informado ou uma descrição informada. Estas regras foram definidas por nós e, com certeza, você as implementaria de formas diferentes, porém com as mesmas finalidades. Esta regra é definida através de uma sobre-carga do método RemoverDados(). A atualização dos dados é realizada solicitando ao usuário os valores dos campos que serão alterados e a partir do valor do parâmetro de filtro, que pode ser o código ou a descrição do projeto. A definição dos campos das tabelas foi feita através do método getCampos() da classe Projetos, de forma que, ao se passar um número do campo desejado, o método retornará o nome do campo. Veja que a idéia principal é tornar o processo de manipulação das tabelas simples e direto, sem que o programador tenha que recorrer a estruturas complexas e, principalmente, à sintaxe dos comandos em SQL doMySQL. Para finalizar, a listagem de dados pode ser de três formas diferentes: Listagem de todos os dados. Listagem dos dados a partir de um código informado. Listagem dos dados a partir de uma descrição informada. Note que a classe de regras do banco de dados possui todas as funcionalidades necessárias para a manipulação dos projetos. Seção 2 - Representação das Principais Funcionalidades Para facilitar a compreensão dos principais métodos executados na classe de banco de dados que manipula a tabela Projeto, acompanhe, agora, a apresentação de tarefas executadas, sem se prender às notações padronizadas para esta representação. Unidade 9 Linguagens de Programação II.indb 191 191 7/12/2006 14:01:00 Universidade do Sul de Santa Catarina Veja que o objetivo principal é compreender o fluxo de execução destes métodos. Método de Inserção O método de inserção possui o seguinte processo de execução: 1) Instancia-se uma classe do tipo Projeto; 2) Preenchem-se os dados da classe Projeto através do método LeiaDados(); 3) Se há consistência dos dados, então a) Gera-se uma String com os nomes das colunas, separados por vírgulas; b) Os nomes dos campos são recuperados através do método getCampos(); c) Gera-se a estrutura com os valores de inserção de campos; d) Os valores de campos que não são numéricos, são colocados entre aspas (“) através do método QuotedStr(), ou mudados para o formato de data aceita pelo MySQL; e) Os valores de cada campo são separados por vírgula; f) Gera-se um comando com a estrutura: Insert into Tabelas(coluna, coluna, ..., coluna) values (valor, valor, ..., valor); g) O comando é executado através do método ExpressaoSQL(); h) Se houver um erro de Exceção, então; a) Aborta-se a inserção; 4) Senão a) Aborta-se a inserção; 192 Linguagens de Programação II.indb 192 7/12/2006 14:01:00 Linguagens de Programação II Método de Remoção de Dados O método de remoção de dados possui o seguinte processo de execução: 1) Verifica-se o tipo de remoção 2) Se parâmetro é Código, então a) Gera-se um comando com a estrututura: Delete from Projetos where idProjetos = “ + Codigo 3) Senão a) Gera-se um comando com a estrututura: Delete from Projetos where vDescricao = “ + QuotedStr(Descricao); 4) Se houver um erro de Exceção, então a) Aborta-se a Remoção; Método de Listagem de Dados O método de listagem de dados possui o seguinte processo de execução: 1) Verifica-se o tipo de Listagem 2) Se parâmetro é Código, então a) Gera-se um comando com a estrututura : Select * from Projetos where idProjetos = “ + Codigo 3) Senão Se parâmetro é Descrição, então a) Gera-se um comando com a estrututura : Select * from Projetos where vDescricao = “ + QuotedStr(Descricao); Senão Unidade 9 Linguagens de Programação II.indb 193 193 7/12/2006 14:01:00 Universidade do Sul de Santa Catarina a) Gera-se um comando com a estrututura : Select * from Projetos; 4) Se houver um erro de Exceção, então a) Aborta-se a listagem; Para finalizar, veja a representação de fluxo de execução do último método, o método de atualização de dados. Método de Atualização de Dados O método de atualização de dados possui o seguinte processo de execução: 1) Solicita-se o campo que será ou não atualizado; 2) Se a opção é igual a ‘S’, então a) Armazena-se o Nome da Coluna e solicita-se o valor de cadastramento para esta coluna; b) Separam-se as colunas e os valores por vírgula; c) Se o campo for data, converte-se para o formado de data do MySQL; d) Se o campo não for numérico, os valores serão colocados entre aspas; 3) Gera-se um comando com a estrututura: Update Tabela Set Coluna = valor, Coluna = valor, ..., Coluna = Valor; 4) Retira-se a vírgula do final do comando montado; 5) O comando é executado através do método ExpressaoSQL(); 6) Se houver um erro de Exceção, então a) Aborta-se a atualização; 194 Linguagens de Programação II.indb 194 7/12/2006 14:01:00 Linguagens de Programação II Seção 3 - Código fontes da Classe de Manipulação dos Projetos Nesta seção, as regras apresentadas acima são codificadas em Java, de forma que elas sejam mantidas durante a execução do programa pelo computador, ou seja, as mesmas regras, porém formalizadas em código-fonte. A estrutura da classe possui o seguinte código fonte: import javax.swing.*; import java.sql.*; import java.util.Vector; public class Manipula_Projeto { private Conexao MinhaConexao; public Manipula_Projeto(Conexao con){ setConexao(con); } public void setConexao(Conexao con){MinhaConexao = con;} public Conexao getConexao(){return MinhaConexao;} //Regras de Negócio private String QuotedStr(String Item) {return “\’”+ Item + “\’”;} private String DataSQL(String Data) { return Data.substring(6,10)+’-’+Data.substring(3,5)+’-’+Data.substring(0,2); } public void InsereDados(){ Projetos Proj = new Projetos(); Proj.LeiaDados(true); if (Proj.getConsistencia()){ String Colunas = “(“+ Proj.getCampos().get(1)+”,”+ Proj.getCampos().get(2)+”,”+ Proj.getCampos().get(3)+”,”+ Proj.getCampos().get(4)+”,”+ Proj.getCampos().get(5)+”)”; String Valores = “(“+ QuotedStr(Proj.getDescricao())+”,”+ QuotedStr(DataSQL(Proj.getDataInicio()))+”,”+ QuotedStr(DataSQL(Proj.getDataFinal()))+”,”+ Proj.getPercentual()+”,”+ QuotedStr(Proj.getSituacao())+”)”; String Comando = “Insert into Projetos”+Colunas + “ values” +Valores; getConexao().ExpressaoSQL(Comando); } } public void RemoverDados(int Codigo){ try{ getConexao().ExpressaoSQL(“ Delete from Projetos where idProjetos = “ + Codigo); getConexao().getCon().commit(); } Unidade 9 Linguagens de Programação II.indb 195 195 7/12/2006 14:01:00 Universidade do Sul de Santa Catarina catch(Exception sqle){ JOptionPane.showMessageDialog(null,”Os dados não foram removidos!”,””, JOptionPane. WARNING_MESSAGE); } } public void RemoverDados(String Descricao){ try{ getConexao().ExpressaoSQL(“ Delete from Projetos where vDescricao = “ + QuotedStr(Descricao)); getConexao().getCon().commit(); } catch(Exception sqle){ JOptionPane.showMessageDialog(null,”Os dados não foram removidos!”,””, JOptionPane. WARNING_MESSAGE); } } public void ListarDados(){ boolean Listou = false; try{ getConexao().ExpressaoSQL(“ Select * from Projetos “); ResultSet rs = getConexao().getDados(); if (rs != null){ while (rs.next()){ Listou = true; Projetos p = new Projetos(); int ID = rs.getInt(“idProjetos”), PERC = rs.getInt(“nPercConcluido”); String DESC = rs.getString(“vDescricao”), SIT =rs.getString(“vSituacao”); String DATAIN = rs.getString(“dDataInicio”), DATAFIN = rs.getString(“dDataFinal”); p.setIdProjeto(ID); p.setDescricao(DESC); p.setDataInicio(DATAIN); p.setDataFinal(DATAFIN); p.setPercentual(PERC); p.setSituacao(SIT); p.ShowDados(); } if(!Listou) JOptionPane.showMessageDialog(null,”Nenhum registro selecionado!”,””, JOptionPane. WARNING_MESSAGE); } } catch(Exception sqle){ JOptionPane.showMessageDialog(null,”Os dados não foram listados!”,””, JOptionPane. WARNING_MESSAGE); } } 196 Linguagens de Programação II.indb 196 7/12/2006 14:01:00 Linguagens de Programação II public void ListarDados(int Codigo){ boolean Listou = false; try{ getConexao().ExpressaoSQL(“ Select * from Projetos where IdProjetos = “ + Codigo); ResultSet rs = getConexao().getDados(); if (rs != null){ while (rs.next()){ Listou = true; Projetos p = new Projetos(); int ID = rs.getInt(“idProjetos”), PERC = rs.getInt(“nPercConcluido”); String DESC = rs.getString(“vDescricao”), SIT =rs.getString(“vSituacao”); String DATAIN = rs.getString(“dDataInicio”), DATAFIN = rs.getString(“dDataFinal”); p.setIdProjeto(ID); p.setDescricao(DESC); p.setDataInicio(DATAIN); p.setDataFinal(DATAFIN); p.setPercentual(PERC); p.setSituacao(SIT); p.ShowDados(); } if(!Listou) JOptionPane.showMessageDialog(null,”Nenhum registro selecionado!”,””, JOptionPane. WARNING_MESSAGE); } } catch(Exception sqle){ JOptionPane.showMessageDialog(null,”Os dados não foram listados!”,””, JOptionPane. WARNING_MESSAGE); } } public void ListarDados(String Descricao){ boolean Listou=false; try{ getConexao().ExpressaoSQL(“ Select * from Projetos where vDescricao = “ + QuotedStr(Descricao)); ResultSet rs = getConexao().getDados(); if (rs != null){ while (rs.next()){ Listou = true; Projetos p = new Projetos(); int ID = rs.getInt(“idProjetos”), PERC = rs.getInt(“nPercConcluido”); String DESC = rs.getString(“vDescricao”), SIT =rs.getString(“vSituacao”); Unidade 9 Linguagens de Programação II.indb 197 197 7/12/2006 14:01:00 Universidade do Sul de Santa Catarina String DATAIN = rs.getString(“dDataInicio”), DATAFIN = rs.getString(“dDataFinal”); p.setIdProjeto(ID); p.setDescricao(DESC); p.setDataInicio(DATAIN); p.setDataFinal(DATAFIN); p.setPercentual(PERC); p.setSituacao(SIT); p.ShowDados(); } if(!Listou) JOptionPane.showMessageDialog(null,”Nenhum registro selecionado!”,””, JOptionPane. WARNING_MESSAGE); } } catch(Exception sqle){ JOptionPane.showMessageDialog(null,”Os dados não foram listados!”,””, JOptionPane. WARNING_MESSAGE); } } public void AtualizarDados(int Codigo){ Projetos P = new Projetos(); String Comando = “ Update Projetos set “; String Campos [] = {“Descrição”, “Data de Início”, “Data de Encerramento”, “Percentual”, “Situação”}; for (int i=0;i<Campos.length;i++){ if ((JOptionPane.showInputDialog(“Atualizar o Campo [“ + Campos[i]+”]”,”S”).toUpperCase()).charAt(0)==’S’){ String Valor = JOptionPane.showInputDialog(“Novo Valor para “+ Campos[i]); switch (i){ case 0:Valor = QuotedStr(Valor);break; case 1:Valor = QuotedStr(DataSQL(Valor));break; case 2:Valor = QuotedStr(DataSQL(Valor));break; case 4:Valor = QuotedStr(Valor);break; } Comando+= ((String)P.getCampos().get(i+1))+”=”+Valor+”,”; } } if(Comando.length() > 0 && Comando.charAt(Comando.length()-1)==’,’){ Comando = Comando.substring(0,Comando.length()-1); } Comando += “ where idProjetos = “ + Codigo; try{ getConexao().ExpressaoSQL(Comando); } 198 Linguagens de Programação II.indb 198 7/12/2006 14:01:01 Linguagens de Programação II catch (Exception sqle) { JOptionPane.showMessageDialog(null,”Os dados não foram atualizados!”,””, JOptionPane. WARNING_MESSAGE); } } public void AtualizarDados(String Descricao){ Projetos P = new Projetos(); String Comando = “ Update Projetos set “; String Campos [] = {“Descrição”, “Data de Início”, “Data de Encerramento”, “Percentual”, “Situação”}; for (int i=0;i<Campos.length;i++){ if ((JOptionPane.showInputDialog(“Atualizar o Campo [“ + Campos[i]+”]”,”S”).toUpperCase()).charAt(0)==’S’){ String Valor = JOptionPane.showInputDialog(“Novo Valor para “+ Campos[i]); switch (i){ case 0:Valor = QuotedStr(Valor);break; case 1:Valor = QuotedStr(DataSQL(Valor));break; case 2:Valor = QuotedStr(DataSQL(Valor));break; case 4:Valor = QuotedStr(Valor);break; } Comando+= ((String)P.getCampos().get(i+1))+”=”+Valor+”,”; } } if(Comando.length() > 0 && Comando.charAt(Comando.length()-1)==’,’){ Comando = Comando.substring(0,Comando.length()-1); } Comando += “ where vDescricao = “ + QuotedStr(Descricao); try{ getConexao().ExpressaoSQL(Comando); } catch (Exception sqle) { JOptionPane.showMessageDialog(null,”Os dados não foram atualizados!”,””, JOptionPane. WARNING_MESSAGE); } } } Atente para algumas características importantes da classe acima: O método QuotedStr(String Item) retorna um valor literal entre aspas duplas (“). Unidade 9 Linguagens de Programação II.indb 199 199 7/12/2006 14:01:01 Universidade do Sul de Santa Catarina O método DataSQL(String Data) retorna a data no formato que o MySQL utililiza, que é “aaaa-mm-dd”; O método getCampos().get(índice) retorna o nome do campo indexado pelo índice informado; Os comandos gerados são passados como parâmetro para o método ExpressaoSQL(Comando); O ideal é que você edite e compile a classe acima, para se adequar aos conceitos e formas de programação apresentadas por nós. Seção 4 – Testando a Classe de Manipulação dos Projetos Para testar a classe de manipulação de dados, é necessário que seja implementada uma nova classe, conforme o código abaixo: public class teste { public static void main(String[] args) { Conexao C = new Conexao(“localhost”,”livro”,”root”,”root”); C.Conectar(); if (C.getConectado()){ Manipula_Projeto MP = new Manipula_Projeto(C); //Insere dois Projetos MP.InsereDados(); MP.InsereDados(); //Remove o Projeto de Código 1 MP.RemoverDados(1); //Lista os Projetos cadastrados MP.ListarDados(); //Atualiza o projeto de descrição chamada TESTE MP.AtualizarDados(“TESTE”); C.FecharConexao(); } } } 200 Linguagens de Programação II.indb 200 7/12/2006 14:01:01 Linguagens de Programação II Na classe “teste”, o usuário poderá inserir, alterar, excluir e listar dados da tabela Projetos, criada no MySQL. Compile e execute a classe acima e veja o funcionamento da mesma. Seção 5 – Estrutura das demais classes As classes de manipulação de participantes e controles de projetos possuem a mesma estrutura da classe de manipulação de projetos. As classes de regras de banco de dados possuem uma estrutura padronizada, cuja finalidade é popular e manipular os dados das tabelas. Não vamos apresentar aqui o código-fonte das demais classes, pois seria repetitivo demais. Porém, os códigos completos podem ser baixados na midiateca do espaço UnisulVirtual de Aprendizagem (EVA), de forma que você possa compilá-las e executá-las por completo. O ideal, a partir de agora, é você agrupar os conhecimentos das unidades estudadas anteriormente e criar uma identidade visual para a aplicação, de forma que esta possua uma camada de interface gráfica e as regras de banco de dados, criando-se, assim, uma aplicação completa. Unidade 9 Linguagens de Programação II.indb 201 201 7/12/2006 14:01:01 Universidade do Sul de Santa Catarina Síntese Nesta unidade, você pôde colocar em prática os ensinamentos adquiridos nas unidades anteriores. Porém, isto é um pequeno passo rumo ao desenvolvimento de softwares. Com a união dos conhecimentos de interfaces gráficas (GUI) e regras de banco de dados, você já poderá criar aplicações mais robustas e mais amigáveis. Este é o primeiro passo para a criação de classes que permitam a conexão com banco de dados e a implementação de aplicações para o ambiente da internet, mas isto é assunto para as próximas unidades. Boa sorte nesta nova caminhada. Atividades de auto-avaliação Efetue as atividades de auto-avaliação e, a seguir, acompanhe as respostas e comentários a respeito. Para melhor aproveitamento do seu estudo, realize a conferência de suas respostas somente depois de fazer as atividades propostas. Leia com atenção os enunciados e realize, a seguir, as atividades: 1) Uma aplicação Desktop pode ser migrada para um ambiente web sem muitas alterações? 202 Linguagens de Programação II.indb 202 7/12/2006 14:01:01 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: HORSTMANN, Cay S. Big Java. Porto Alegre: Artmed Bookman: 2004. THOMPSON, Marco Aurélio. Java 2 & banco de dados. São Paulo, Érica: 2002. Unidade 9 Linguagens de Programação II.indb 203 203 7/12/2006 14:01:01 Linguagens de Programação II.indb 204 7/12/2006 14:01:02 UNIDADE 10 Aplicação Exemplo: Controle de Projetos Objetivos de aprendizagem Entender como aplicar os conceitos de criação de GUI e manipulação de banco de dados, através visualização do código de uma aplicação de Controle de Projetos. Seções de estudo Seção 1 Linguagens de Programação II.indb 205 Elementos da aplicação de Controle de Projetos 7/12/2006 14:01:02 Universidade do Sul de Santa Catarina Para início de conversa Nesta unidade você visualizará o código completo de uma aplicação gráfica com acesso a banco de dados. Essa aplicação foi denominada de Controle de Projetos. É uma aplicação que objetiva controlar de maneira simplificada dados de projetos e de pessoas que trabalham nos projetos. O objetivo dessa unidade é fazer a integração dos conhecimentos das unidades de GUI e das unidades de Banco de Dados. O banco de dados da aplicação já foi criado por você nas unidades seis (6) a nove (9). A GUI da aplicação e a parte de controle dos dados serão exibidos no código-fonte da aplicação, que está disponibilizada na Midiateca. Seção 1 – Elementos da aplicação de Controle de Projetos A aplicação possuirá uma tela inicial com um menu principal contendo as opções: Cadastro e Consulta. Na opção Cadastro será possível escolher as opções Projetos e Participantes. Na opção Consulta será possível escolher as opções Projetos e Participantes. 206 Linguagens de Programação II.indb 206 7/12/2006 14:01:02 Linguagens de Programação II Síntese Nessa unidade você aprendeu a construir uma aplicação completa, integrando os conceitos aprendidos nas unidades um (1) a cinco (5) (que abordam a GUI) e seis (6) a nove (9) (que tratam do Banco de Dados). Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando a seguinte referência, principalmente os capítulos 10, 11 e 22: DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. Também consulte: SILVA, Ivan José de Mecenas. Java 2: fundamentos Swing e JDBC. Rio de Janeiro: Editora Alta Books, 2003. Consulte, também, o seguinte site: http://java.sun.com/docs/books/tutorial/uiswing/index.html (Creating a GUI with JFC/Swing) Unidade 10 Linguagens de Programação II.indb 207 207 7/12/2006 14:01:02 208 Linguagens de Programação II.indb 208 7/12/2006 14:01:02 UNIDADE 11 Introdução ao desenvolvimento de aplicações web 11 Objetivos de aprendizagem Entender como funciona o protocolo http. Aprender o que são as aplicações CGI. Entender o ambiente necessário para o desenvolvimento de aplicações Java na web. Seções de estudo Seção 1 HTTP Seção 2 CGI Seção 3 Java Servlets e Containers Seção 4 Preparando o Ambiente Linguagens de Programação II.indb 209 7/12/2006 14:01:02 Universidade do Sul de Santa Catarina Para início de conversa No início da Internet, todo o conteúdo era baseado em sites de conteúdo estático. Ou seja, todas as páginas eram compostas por conteúdos pré-definidos e que só podiam ser alterados caso o seu autor fizesse a alteração do conteúdo manualmente. Entretanto, com o passar do tempo houve a necessidade de uma maior interação entre os usuários e essas páginas estáticas, fazendo com que surgissem as primeiras aplicações web com páginas dinâmicas, onde o conteúdo das páginas era gerado com base nas interações do usuário com o sistema. Visando a atender essa necessidade, surgiu o Common Gateway Interface (CGI), uma das primeiras e mais proeminentes soluções para o desenvolvimento de aplicações geradoras de conteúdo dinâmico, ou seja, aplicações web. Compreender como o CGI funciona é muito importante, uma vez que ele responde a muitas questões relacionadas ao desenvolvimento de aplicações web em Java, como, por exemplo, por que as aplicações web Java precisam de um ambiente próprio de execução? Um conjunto específico de regras ou padrões relacionados às comunicações entre computadores. Porém, antes de entendermos o que é o CGI e como ele trabalha, iremos conhecer o protocolo de comunicação mais utilizado em aplicações web hoje em dia, o HyperText Transfer Protocol ou, simplesmente, HTTP. 210 Linguagens de Programação II.indb 210 7/12/2006 14:01:02 Linguagens de Programação II Seção 1 - HTTP O HTTP é um protocolo que permite a servidores e browsers trocarem informações sobre a Internet. A estrutura da comunicação utilizando o HTTP é bem simples, pois se baseia na requisição/resposta. Um browser requisita um recurso e um servidor responde enviando o recurso. Veja na figura 11.1 como é feita essa comunicação: REQUISIÇÃO RESPOSTA Cliente Servidor Web FIGURA 11.1 - FIGURA BÁSICA SOBRE REQUEST E RESPONSE Ambos os itens da comunicação, a requisição e a resposta, possuem um formato padrão. Antes de falarmos destes formatos, é preciso que você entenda um pouco a respeito do método em que as requisições podem ser feitas. O HTTP possibilita que uma requisição possa ser feita utilizando 8 métodos. Porém, os mais utilizados são o GET e o POST. Qual seria a diferença entre os dois? Os dois métodos têm o mesmo propósito, porém trabalham de forma diferente. O GET adiciona à URL todas as informações que você envia ao servidor, como no exemplo abaixo: http://www.google.com.br/search?hl=pt-BR&q=GET+vs+POST&meta= Repare que, em uma pesquisa no Google, o nosso tema da busca (GET vs POST) foi adicionado à URL quando essa requisição foi enviada ao servidor. Unidade 11 Linguagens de Programação II.indb 211 211 7/12/2006 14:01:02 Universidade do Sul de Santa Catarina Se a mesma requisição fosse feita utilizando o método POST, ela teria o seguinte formato: http://www.google.com.br/search Neste caso, as informações a respeito da busca não seriam perdidas e, sim, seriam enviadas em uma outra área destinada justamente aos dados de uma requisição. Mas por que, então, devemos nos preocupar em estar utilizando um método ou outro? Aqui vão algumas razões pelas quais você deve estar escolhendo um método ou outro: O total de caracteres numa requisição utilizando o GET é limitado. Ou seja, alguns servidores poderão cortar o conteúdo da URL, já que no método GET toda a informação é concatenada na URL, fazendo com que a requisição não funcione. Se algum dado sigiloso, uma senha, por exemplo, for enviado utilizando o método GET ele ficará exposto, pois será concatenado à URL e mostrado no browser. Vendo esses pontos, você deve perguntar-se por que, então, existe o método GET? Ora, em alguns cenários o GET é mais indicado que o POST, como, por exemplo, quando executamos apenas consultas no sistema que não irão alterar o estado da nossa aplicação. O próprio Google utiliza o método GET para realizar as suas buscas. A seguir, no quadro 1, mostramos como os dois métodos utilizam o HTTP para envio de requisição: 212 Linguagens de Programação II.indb 212 7/12/2006 14:01:03 Linguagens de Programação II GET /aplicacao/compra.do?valor=10 Host: www.endereco.com.br User-Agent: Mozilla 5.0 Accept: text/html, application/xml, …. Accept-Language: pt-br …. Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859, utf-8;…. Keep-Alive: 300 Connection: keep-alive POST /aplicacao/compra.do Host: www.endereco.com.br User-Agent: Mozilla 5.0 Accept: text/html, application/xml, …. Accept-Language: pt-br …. Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859, utf-8;…. Keep-Alive: 300 Connection: keep-alive valor=10 Quadro 1 – Anatomia dos métodos GET e POST Tendo visto os métodos e o formato em que é enviada uma requisição, falta você verificar qual o formato de uma resposta HTTP. Ao contrário da requisição, a resposta não tem método e sim o tipo de conteúdo (página HTML, arquivo de som, vídeo, etc.) que está sendo retornado ao browser. O formato de uma resposta HTTP é apresentado no quadro 2: HTTP/1.1 200 OK Set-Cookie: JSESSIONID=0AAB6C8DEA415E2E5….; Path=/teste Content-Type: text/html Content-Length: 397 Date: Mon, 15 Ago 2005 12:45:55 GMT Server: Apache-Coyote/1.1 Connection: close <html> …… </html> Quadro 2 - Anatomia de uma resposta HTTP Agora que vimos o protocolo HTTP que é utilizado nas aplicações web, podemos começar a ver as tecnologias utilizadas para a construção de aplicações web. Unidade 11 Linguagens de Programação II.indb 213 213 7/12/2006 14:01:03 Universidade do Sul de Santa Catarina Seção 2 - CGI O CGI geralmente é referenciado como uma das primeiras tecnologias para a criação de conteúdo dinâmico no lado do servidor. Apesar de ser referenciado desta forma, CGI não é uma linguagem de programação e sim um protocolo de comunicação que possibilita a um servidor comunicar-se com uma aplicação externa. Essas aplicações podem ser escritas em qualquer linguagem de programação, porém a linguagem mais utilizada é o Perl. De forma simplificada, o processo de comunicação entre o servidor que recebe requisições e uma aplicação CGI ocorre da seguinte forma: o servidor web encaminha a requisição de um usuário a uma aplicação, esta aplicação é executada, cria algum conteúdo e envia a resposta novamente ao servidor que, então, encaminha ao cliente. O processo é ilustrado na figura 11.2: CGI Cliente Aplicação CGI Servidor Web Banco de Dados FIGURA 11.2 – FLUXO DE UMA APLICAÇÃO CGI O surgimento do CGI foi um grande avanço perante o conteúdo estático da Internet. Apesar de ter sido uma revolução nas aplicações web, o CGI apresentava algumas falhas, dentre elas se destaca o modo como era gerenciado o ciclo de vida de aplicações CGI. De maneira simples, podemos pensar no ciclo de vida como sendo todo o processo, desde o recebimento de uma solicitação até a entrega do resultado da mesma. Quando um servidor web recebe uma requisição que será encaminhada a uma aplicação CGI, um processo é criado e para cada nova solicitação um novo processo será criado. Como a criação, inicialização e finalização de um processo possui um custo relativamente alto, dependendo do grau de utilização do servidor, em pouco tempo o mesmo sofrerá uma queda drástica de performance da aplicação e o servidor sofrerá uma drástica redução de performance. 214 Linguagens de Programação II.indb 214 7/12/2006 14:01:03 Linguagens de Programação II Uma analogia pode ser feita com o processo de ligar e desligar um computador. Imagine que o custo de criação, inicialização e finalização de um novo processo seja semelhante ao custo de ligar o computador, utilizá-lo e desligá-lo. Ou seja, a cada requisição o computador seria ligado, efetuaria algum processamento e seria desligado. A figura 11.3 ilustra o ciclo de vida de uma aplicação CGI: Servidor Web Requisição Processo CGI Requisição Processo CGI Requisição Processo CGI FIGURA 11.3 – CICLO DE VIDA DE UMA APLICAÇÃO GCI A popularidade do CGI fez com que nascesse a segunda geração de aplicações CGI, chamadas de aplicações FastCGI, onde o problema apresentado pela primeira versão, relacionado à criação de um processo para cada requisição, foi contornado, pois as requisições que tinham a mesma finalidade compartilhavam os mesmos processos. Isto tornou o CGI uma solução muito mais prática para as aplicações web. A figura 11.4 apresenta o novo ciclo de vida proposto pelas aplicações FastCGI. Servidor Web Requisição Processo CGI Requisição Processo CGI Requisição Processo CGI FIGURA 11.4 – CICLO DE VIDA DE APLICAÇÕES FASTCGI Unidade 11 Linguagens de Programação II.indb 215 215 7/12/2006 14:01:03 Universidade do Sul de Santa Catarina Entretanto, apesar da questão relacionada à criação de processos ter sido resolvida com o FastCGI, surgiram algumas outras questões que tornaram o CGI uma solução não muito atrativa. Um exemplo é a dificuldade de compartilhar recursos entre as requisições como: utilitários para a geração de log da aplicação, objetos, entre outros. Uma nova solução era demandada para aplicações web corporativas, preferencialmente uma que não tivesse os problemas apresentados pelo CGI. Seção 3 - Java Servlets e Containers Para resolver os problemas apresentados pelas aplicações CGI, a empresa Sun criou a especificação Java Servlets. Funcionando de maneira similar às aplicações CGI, os Servlets recebem as requisições de um servidor web e geram um conteúdo dinâmico. Porém, os Servlets definem um ciclo de vida mais eficiente comparado ao ciclo de vida das aplicações CGI, evitando, assim, o custo da criação de vários processos para cada requisição. A figura 11.5 apresenta um servidor web com o suporte da Java Servlets. Servidor Web Processo Requisição Servlet Requisição Servlet Requisição Servlet FIGURA 11.5 – AMBIENTE DE EXECUÇÃO DE SERVLETS 216 Linguagens de Programação II.indb 216 7/12/2006 14:01:03 Linguagens de Programação II A figura 11.5 é semelhante à figura 11.4, em que era apresentada a segunda geração das aplicações CGI ou FastCGI. Porém, note que, na figura 11.5, todos os Servlets estão sendo executados dentro do mesmo processo. Aliada às vantagens da plataforma Java, a tecnologia dos Servlets, especificada pela Sun, resolveu os problemas apresentados pelas aplicações CGI e tornou-se uma das soluções mais populares para a geração de conteúdo dinâmico no lado do servidor. Porém, para conseguir alcançar todos os seus objetivos, os Servlets precisam de um ambiente adequado para a sua execução. Este ambiente se chama Servlet Container e é responsável por gerenciar todo o ciclo de vida dos servlets. Assim como a especificação dos Servlets, o Servlet Container também é uma especificação. Ou seja, ela apenas define características e itens que, para ser um Serlvet Container, precisam ser atendidas, dessa forma possibilitando a cada fornecedor implementar a especificação da maneira que achar mais conveniente. A seguir, será apresentado um passo a passo para a instalação do ambiente onde serão executados os Servlets. Seção 4 – Preparando o Ambiente A fundação Apache possui uma implementação da especificação do Servlet Container, e essa implementação é chamada de Apache Tomcat, devido a sua grande utilização e por essa implementação ter se tornada uma referência entre as implementações da especificação Java Servlets. Assim, ela será a nossa escolha para ser o ambiente de execução dos Java Servlets. O Apache Tomcat está disponível no endereço http://tomcat.apache.org/ Contudo, essa versão do Tomcat exige a utilização do Java 5. Unidade 11 Linguagens de Programação II.indb 217 217 7/12/2006 14:01:03 Universidade do Sul de Santa Catarina A seguir, a página inicial do projeto é apresentada na figura 11.6: FIGURA 11.6 – PÁGINA DO PROJETO APACHE TOMCAT Utilizaremos a versão 5.5.17 do Apache Tomcat. Portanto, no item Download, escolheremos a opção Tomcat 5.x. Na página seguinte - onde são apresentados os arquivos da versão 5.5.17: Core, Deployer, Embedded, Administration Web Application, JDK 1.4 Compability Package, Documentation - utilizaremos apenas o arquivo Core, pois ele contém o essencial da distribuição e os outros arquivos são módulos adicionais que podem ser instalados no Tomcat posteriomente. Porém, é necessária a instalação do pacote Core para que eles possam funcionar. 218 Linguagens de Programação II.indb 218 7/12/2006 14:01:04 Linguagens de Programação II Utilizaremos a versão executável do arquivo Core. Após o término do download, execute o instalador do Tomcat e siga os passos: FIGURA 11.7 – TELA INICIAL DA INSTALAÇÃO Inicialmente, será apresentada uma tela de boas vindas com algumas recomendações. Seguidas as recomendações, você pode avançar na instalação clicando no botão Next e indo para a próxima tela apresentada na figura 11.8: FIGURA 11.8 – TERMOS DA LICENÇA DO TOMCAT Unidade 11 Linguagens de Programação II.indb 219 219 7/12/2006 14:01:04 Universidade do Sul de Santa Catarina Nessa tela, são apresentados os termos da licença de utilização do Tomcat. Não é algo com que você deve se preocupar, pois o Tomcat é uma aplicação Open Source, ou seja, você pode utilizála sem ter que pagar nenhuma taxa. Tendo lido os termos da licença, você pode concordar com eles e avançar para a próxima etapa clicando no botão I Agree apresentado na figura 11.9: FIGURA 11.9 – TIPO DE INSTALAÇÃO A SER FEITA Na tela apresentada na figura 11.9, você escolherá que tipo de instalação será feita. Para fins didáticos, podemos selecionar a instalação ‘Normal’ e avançar para a próxima etapa clicando no botão Next. FIGURA 11.10 – LOCAL DE INSTALAÇÃO 220 Linguagens de Programação II.indb 220 7/12/2006 14:01:04 Linguagens de Programação II Nesta tela, você escolherá onde o Tomcat será instalado. Nessa etapa, é recomendado que o Tomcat seja instalado em algum drive raiz para evitar problemas futuros de compilação. Porém, fique à vontade para instalar o Tomcat em qualquer diretório. Tendo escolhido o diretório, vamos para a próxima etapa, clicando no botão Next, onde veremos uma tela semelhante à apresentada na figura 11.11. FIGURA 11.11 – CONFIGURAÇÃO DE ADMINISTRAÇÃO A tela apresentada na figura 11.11 possibilita que sejam informadas: a porta em que o Tomcat irá rodar, o usuário e a senha de administração. A porta de execução do Tomcat geralmente não é utilizada, podendo ser mantida a sugestão da porta 8080. Porém, caso ela esteja sendo utilizada por alguma aplicação, fique à vontade para mudá-la. FIGURA 11.12 – LOCALIZAÇÃO DO JRE Unidade 11 Linguagens de Programação II.indb 221 221 7/12/2006 14:01:05 Universidade do Sul de Santa Catarina Como veremos mais à frente, os Servlets são classes Java e para serem executados devem rodar sobre uma máquina virtual Java. Por isso, na tela apresentada na figura 11.12, você deve localizar onde está instalada a máquina virtual do java no seu computador para poder utilizar o Tomcat. Após a localização, podemos ir para a próxima etapa clicando no botão Next. FIGURA 11.13 – FINALIZAÇÃO DA INSTALAÇÃO DO TOMCAT Pronto, a instalação do Tomcat foi concluída. Nessa tela há informações sobre a finalização do processo de instalação, as opções para iniciar o Tomcat e a leitura de um arquivo com algumas informações. Podemos, então, clicar no botão Finish. Logo após, você pode acessar o Tomcat pelo navegador utilizando o endereço http://localhost:8080/, que irá exibir uma página semelhante à figura 11.14: 222 Linguagens de Programação II.indb 222 7/12/2006 14:01:05 Linguagens de Programação II FIGURA 11.14 – PÁGINA INICIAL DO TOMCAT Se você visualizou uma página semelhante à figura 11.14, a sua instalação foi efetuada com sucesso. . Note que, na barra de inicialização rápida, aparece o seguinte ícone É a partir deste ícone que você irá controlar o Tomcat para inicializá-lo e finalizá-lo. Agora, com o ambiente instalado, estamos prontos para começarmos o próximo capítulo em que iniciaremos o desenvolvimento de aplicações web utilizando Servlets. Unidade 11 Linguagens de Programação II.indb 223 223 7/12/2006 14:01:05 Universidade do Sul de Santa Catarina Síntese Nessa unidade vimos os conceitos e algumas tecnologias relacionadas ao desenvolvimento de aplicações web. É importante lembrar que os conceitos do protocolo HTTP e como ele funciona é fundamental, para que o desenvolvimento de aplicações web possa ser feito da melhor forma. Outro ponto importante é analisar o ciclo de vida das aplicações que utilizam CGI, para você ter uma base de comparação quando estudar a unidade sobre Java Servlets. Por último, o ambiente de execução dos Java Servlets, no nosso caso o Apache Tomcat, será de grande importância para que a execução de aplicações web que utilizem Java possa ser feita da melhor forma. Atividades de auto-avaliação A partir de seus estudos, leia com atenção e resolva as atividades programadas para a sua auto-avaliação. 1) Qual tecnologia permitiu que as páginas estáticas da web pudessem ser tornar dinâmicas? 2) Quais métodos de requisição HTTP são os mais utilizados? 3) Qual o nome da estrutura necessária para a execução dos Java Servlets? 224 Linguagens de Programação II.indb 224 7/12/2006 14:01:06 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: http://tomcat.apache.org/ (Site oficial do projeto Apache Tomcat) http://java.sun.com/products/servlet/ (Site oficial da Sun sobre a tecnologia Java Servlets) http://www.jcp.org/aboutJava/communityprocess/final/jsr154/index.html (Site da especificação dos Java Servlets) http://www.w3.org/CGI/ (Site do consórcio W3C sobre a tecnologia CGI) http://www.w3.org/Protocols/ (Site do consórcio W3C sobre o protocolo http) Unidade 11 Linguagens de Programação II.indb 225 225 7/12/2006 14:01:06 Linguagens de Programação II.indb 226 7/12/2006 14:01:06 UNIDADE 12 Java Servlets Objetivos de aprendizagem Entender como funciona a tecnologia Java Servlets. Conhecer os recursos disponibilizados pela tecnologia Java Servlets. Desenvolver uma aplicação web utilizando a tecnologia Java Servlets. Seções de estudo Seção 1 Introdução aos Java Servlets Seção 2 Recuperando parâmetros de um formulário Seção 3 Navegando entre Servlets Seção 4 Sessões Linguagens de Programação II.indb 227 7/12/2006 14:01:06 Universidade do Sul de Santa Catarina Para início de conversa Veremos, nesta unidade, o que são os Java Servlets, algumas funcionalidades que eles oferecem e como utilizar tais funcionalidades para desenvolver uma aplicação web. Será discutido, também, a estruturação de aplicações web. Seção 1 – Introdução aos Java Servlets Na unidade anterior você estudou como era a preparação do ambiente de execução dos servlets, porém não viu alguns itens que fazem do Servlet Container algo crucial para a utilização de Servlets. Dentre esses itens destacam-se: Suporte na utilização de um protocolo - você não precisa se preocupar como o Servlet Container irá receber as requisições feitas pelo browser, você apenas implementa a sua lógica nos Servlets e os utiliza. Gerência do ciclo de vida - o Servlet Container controla todo o ciclo de vida de um Servlet, desde a sua inicialização até a sua destruição, deixando mais uma vez você livre para implementar apenas a sua lógica de negócio. Ambiente multithread - um Servlet Container deve ser um ambiente multithread, ou seja, ele deve ser capaz de receber várias requisições e para cada requisição criar uma thread, que, por sua vez, irá processar a requisição. Os itens apresentados acima não são os únicos que um Servlet Container deve se preocupar. Existem outros, porém esses são os mais evidentes. Até agora, você sabe que um Servlet Container executa Servlets, gerencia o seu ciclo de vida e facilita algumas tarefas de infra-estrutura para o desenvolvedor de Servlets. 228 Linguagens de Programação II.indb 228 7/12/2006 14:01:06 Linguagens de Programação II Porém, você ainda não viu como um Servlet Container trata uma requisição de um browser e como ele responde a essa requisição. Na figura 12.1, o processo é ilustrado para um melhor entendimento. FIGURA 12.1 - PROCESSAMENTO DE UMA REQUISIÇÃO PELO SERVLET CONTAINER Agora que você tem uma visão melhor do Servlet Container e como ele funciona torna-se mais fácil entender e trabalhar com Servlets. Unidade 12 Linguagens de Programação II.indb 229 229 7/12/2006 14:01:06 Universidade do Sul de Santa Catarina Antes de mais nada, um Serlvet é uma classe Java como outra qualquer. Porém, um Servlet precisa de alguns métodos para poder lidar com o protocolo HTTP e tais métodos são herdados da super classe javax.servlet.http.HttpServlet. Esta classe é a base para todos os Servlets. Ela possui métodos relacionados ao modo que as requisições podem ser feitas ao Servlet Container, ou seja, utilizando o get, post, head, etc. Para cada um desses modos o Servlet irá implementar um método com o mesmo nome do modo, porém com o sufi xo “do”, ou seja, doGet, doPost, doHead, etc. Porém, a implementação de todos os métodos não é obrigatória, apenas o método que será utilizado. Talvez as seguintes dúvidas venham a tona: “O Servlet não tem construtor? Onde fica o método main() para poder iniciar a aplicação?” Quem cuida para que um Servlet esteja sempre pronto para receber requisições é o Servlet Container, ou seja, as perguntas que foram feitas anteriormente são resolvidas pelo Servlet Container. A seguir, na figura 12.2, é apresentado um diagrama de classes mostrando a estrutura de classes que um Servlet segue: FIGURA 12.2 - DIAGRAMA DE CLASSE DO PACOTE JAVAX.SERVLET 230 Linguagens de Programação II.indb 230 7/12/2006 14:01:06 Linguagens de Programação II Você pode perceber que além de um Servlet ser uma subclasse da classe abstrata javax.servlet.http.HttpServlet, ele acaba também herdando características da classe javax.servlet.GenericServlet. Essa última classe define a maioria do comportamento do Servlet: como será instanciado, destruído, entre outros. Apesar das classes possuírem muitos métodos, no momento é preciso entender o funcionamento de apenas 3 métodos fundamentais durante o ciclo de vida de uma Servlet, são eles: 1) O método init() é chamado pelo Servlet Container logo após a criação de um Servlet. Porém, antes do mesmo ser executado, esse método possibilita que você inicialize o seu Servlet antes dele receber requisições. Você só irá reescrever esse método caso queira fazer uma inicialização específica no Servlet. 2) Quando chega uma requisição o método service() é chamado e o Servlet Container inicia uma nova thread. Esse método analisa a solicitação, determinando que método HTTP foi utilizado na requisição (GET, POST, etc.) e encaminha a requisição ao respectivo método, doGet, doPost, etc. Dificilmente será necessário reescrever esse método, pois o seu comportamento padrão já faz o trabalho de maneira correta. 3) Neste momento será executado justamente o método onde estará a lógica da aplicação, que são geralmente os métodos doGet e doPost. Quando se está desenvolvendo Servlets somente um desses métodos é reescrito. Veja agora um exemplo de uma aplicação simples onde é utilizado Servlet. Alguns detalhes serão vistos mais a frente, por isso não se assuste com algum item novo. Unidade 12 Linguagens de Programação II.indb 231 231 7/12/2006 14:01:07 Universidade do Sul de Santa Catarina Para a construção do exemplo, devem ser executados os seguintes passos: 1) Crie a seguinte estrutura de diretórios para a aplicação: aplicacao |-src |-WEB-INF |-classes Cuide ao COPIAR E COLAR TRECHOS DE CÓDIGO direto do .PDF. Caso você faça isso, cuide se caracteres especiais não foram juntos para o arquivo. 2) Dentro do diretório src, crie um arquivo chamado MeuPrimeiroServlet.java com o seguinte conteúdo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class MeuPrimeiroServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); java.util.Date hoje = new java.util.Date(); saida.println(“<html>”); saida.println(“<body>”); saida.println(“Hoje é: ” + hoje); saida.println(“</body>”); saida.println(“</html>”); } } 3) Crie um arquivo chamado web.xml. Esse arquivo será o nosso deployment descriptor, dentro do diretório WEB-INF com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> <servlet> <servlet-name>Este eh meu primeiro Servlet</servlet-name> <servlet-class>MeuPrimeiroServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Este eh meu primeiro Servlet</servlet-name> <url-pattern>/servlet</url-pattern> </servlet-mapping> </web-app> 232 Linguagens de Programação II.indb 232 7/12/2006 14:01:07 Linguagens de Programação II 4) Agora, compile o Servlet. Para isso, abra o console de windows e vá até o diretório da sua aplicação, ou seja, o diretório “aplicacao” e digite o comando: javac –classpath $catalina_home/common/lib/servlet-api.jar –d WEB-INF/classes src/ MeuPrimeiroServlet.java Atenção! Lembre-se de dois pontos: o comando deve estar numa linha apenas e substitua $catalina_home pelo diretório onde está localizado o Tomcat. O caminho inteiro do diretório deve estar entre aspas duplas. 5) Copie a pasta da sua aplicação para o diretório $catalina_home/webapps 6) Reinicie o Tomcat. 7) Abra o browser e digite: http://localhost:8080/ aplicacao/servlet e você verá algo semelhante a figura 12.3: FIGURA 12.3 - RESULTADO DA APLICAÇÃO DE EXEMPLO Analisando esse exemplo, perceba que surgiram alguns itens novos: a estrutura de diretórios utilizada, as classes HttpServletRequest e HttpServletResponse no método doGet e o descritor da aplicação (deployment descriptor). Você agora estudará cada um desses itens, começando pelas duas classes novas. Unidade 12 Linguagens de Programação II.indb 233 233 7/12/2006 14:01:07 Universidade do Sul de Santa Catarina Classes HttpServletRequest e HttpServletResponse As classes HttpServletRequest e HttpServletResponse serão sempre passadas como argumentos para qualquer um dos métodos de um Servlet (doGet, doPost, doHead, etc.) referente ao método HTTP (GET, POST, HEAD, etc.) utilizado no envio das informações. Essas duas classes possibilitam que um Servlet tenha acesso tanto ao objeto de requisição quanto ao objeto de resposta. No exemplo anterior não foi utilizado o objeto de requisição HttpServletRequest, porém foi utilizado o objeto de resposta HttpServletResponse para escrever como seria apresentada a saída para o browser. O objeto de requisição geralmente é utilizado quando se quer capturar informações enviadas pelo browser, por exemplo os dados de um formulário. Descritor da aplicação O descritor da aplicação é um documento XML que é distribuído com a aplicação web e tem a finalidade de informar ao Servlet Container dados sobre a aplicação, como por exemplo, os servlets que aplicação possui, questões de segurança que a aplicação deve ter, entre outros detalhes. Porém, é interessante notar, no exemplo visto, que o descritor possuía apenas informações relacionadas ao Servlet que foi desenvolvido e que tais informações bastaram para que o Servlet Container pudesse localizar o Servlet e encaminhar a ele a requisição feita pelo cliente. No descritor da aplicação, você pode notar que foram informados dois elementos: servlet e servletmapping. No elemento servlet é informado um nome qualquer que será atribuído ao Servlet pelo sub-elemento servlet-name e a classe que implementa esse Servlet pelo sub-elemento servletclass. Neste caso, não são utilizados pacotes, porém, se fossem deveria ser informado todo o caminho do pacote. No elemento servlet-mapping é feita uma ligação entre o Servlet informado anteriormente e uma URL, onde o sub-elemento servlet-name referencia o nome do Servet e o sub-elemento url-pattern informa o padrão de URL que será mapeada para esse Servlet. Dessa forma, quando o Servlet Container receber 234 Linguagens de Programação II.indb 234 7/12/2006 14:01:07 Linguagens de Programação II uma requisição que contenha a URL mapeada, ele saberá que deve encaminhar essa requisição ao respectivo Servlet que está vinculado a essa URL. Estrutura de diretórios Por fim, veja que foi utilizada a estrutura de diretórios no desenvolvimento da nossa primeira aplicação web. A Sun criou um padrão de estrutura de diretórios para as aplicações web. Esse padrão é apresentado a seguir, na figura 12.5: FIGURA 12.4 – ESTRUTURA DE APLICAÇÃO WEB Unidade 12 Linguagens de Programação II.indb 235 235 7/12/2006 14:01:07 Universidade do Sul de Santa Catarina Apesar de ter uma variedade de diretórios, nesse momento é preciso se preocupar apenas com alguns diretórios. A tabela abaixo mostra quais são e para que servem esses diretórios: src Diretório onde ficarão armazenados o código fonte das nossas classes Java. web Diretório raiz da aplicação web. WEB-INF Diretório que irá armazenar o descritor da aplicação web (web.xml) bem como outros arquivos de configuração. Lembre-se que esse diretório não é visível ao cliente. onde ficarão armazenadas as bibliotecas necessárias para a execução WEB-INF/lib Diretório da aplicação, por exemplo drivers JDBC. Agora que você viu o que compõe uma aplicação web e acompanhou o exemplo de uma aplicação que apresenta um conteúdo ao usuário, está na hora de incrementar um pouco mais esta aplicação, permitindo que o usuário informe alguns dados e o Servlet faça um processamento com base nos dados informados. Seção 2 - Recuperando parâmetros de um formulário Na aplicação anterior você viu como se utilizam aplicações que utilizem Servlets. Agora é hora de aumentar a interatividade do usuário com a aplicação, fornecendo ao mesmo a possibilidade de informar dados tais que a aplicação seja capaz de recuperá-los e utilizá-los para algum processamento. Você desenvolverá uma aplicação de forma semelhante ao exemplo anterior, seguindo os seguintes passos: 236 Linguagens de Programação II.indb 236 7/12/2006 14:01:08 Linguagens de Programação II 1) Crie a seguinte estrutura de diretórios para a aplicação: aplicacaoWeb |-src |-WEB-INF |-classes 2) Dentro do diretório src crie um arquivo chamado ParametrosServlet.java com o seguinte conteúdo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class ParametrosServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); String nome = request.getParameter(“nome”); String sexo = request.getParameter(“sexo”); String email = request.getParameter(“email”); saida.println(“<html>”); saida.println(“<body>”); saida.println(“Seu nome é : ” + nome + “<br/>”); saida.println(“Seu sexo é : ” + sexo+ “<br/>”); saida.println(“Seu email é : ” + email + “<br/>”); saida.println(“</body>”); saida.println(“</html>”); } } 3) Crie um arquivo chamado index.html com o conteúdo abaixo e o salve na pasta raiz da aplicação, ou seja, na pasta aplicacaoWeb: <html> <body> <form action=”parametros” method=”post”> Nome: <input type=”text” name=”nome” /><p /> Email: <input type=”text” name=”email” /> <p /> Sexo: <select name=”sexo”> <option value=”Masculino”>Masculino</option> <option value=”Feminino”>Feminino</option> </select><p/> <input type=”submit” value=”Enviar”/> </form> </body> </html> Unidade 12 Linguagens de Programação II.indb 237 237 7/12/2006 14:01:08 Universidade do Sul de Santa Catarina Atenção! Repare que na página HTML foi criada um formulário e nesse formulário são informados dois itens importantes: um atributo action que informa que Servlet será utilizado para receber essa requisição. Note que no arquivo web.xml mapeamos um Servlet para receber requisições que obedeçam o padrão ‘/ parametros’; o atributo method foi configurado com o tipo POST, ou seja, o Servlet terá que implementar o método doPost para poder receber esse formulário. 4) Crie um arquivo chamado web.xml. Esse arquivo será o deployment descriptor, dentro do diretório WEB-INF com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> <servlet> <servlet-name>Recupera Parametros</servlet-name> <servlet-class>ParametrosServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Recupera Parametros</servlet-name> <url-pattern>/parametros</url-pattern> </servlet-mapping> </web-app> 5) Agora, compile o Servlet. Para isso, abra o console de windows e vá até o diretório da sua raiz aplicação e digite o comando: javac –classpath $catalina_home/common/lib/servlet-api.jar –d WEB-INF/classes src/ ParametrosServlet.java Atenção! Lembre-se de dois pontos: o comando deve estar numa linha apenas e substitua $catalina_home pelo diretório onde está localizado o Tomcat. O caminho inteiro do diretório deve estar entre aspas duplas. 238 Linguagens de Programação II.indb 238 7/12/2006 14:01:08 Linguagens de Programação II 6) Copie o diretório aplicacaoWeb para o diretório $catalina_home/webapps 7) Reinicie o Tomcat. 8) Digite no browser o endereço http://localhost:8080/ aplicacaoWeb/index.html e você verá uma tela como a figura abaixo: FIGURA 12.5 – FORMULÁRIO DE DADOS Preenchendo as informações e clicando no botão enviar você terá um resultado semelhante à figura 12.7 abaixo: FIGURA 12.6 – PÁGINA DE RESPOSTA Agora que você viu como enviar parâmetros a um Serlvet e como gerar conteúdo para ser exibido ao cliente, você verá como adicionar a essa aplicação a funcionalidade de navegação, ou seja, como poder adicionar links as páginas para se navegar por toda a aplicação e não se ficar somente com uma ou duas páginas. Unidade 12 Linguagens de Programação II.indb 239 239 7/12/2006 14:01:08 Universidade do Sul de Santa Catarina Seção 3 - Navegando entre Servlets Como todo Servlet gera uma saída HTML que será exibida ao usuário, é possível a cada resposta do usuário criar um link para poder vincular vários Servlets e dessa forma aumentar as funcionalidades da nossa aplicação. Pense no seguinte exemplo: um sistema simples de inscrição onde se têm 3 telas, uma para cadastrar os dados pessoais, outra tela para informar o curso desejado e uma tela apresentando o final do processo: 1) Crie novamente a seguinte estrutura de diretórios para a aplicação: sistemaCadastro |-src |-WEB-INF |-classes 2) Dentro do diretório src crie um arquivo chamado CadastraServlet.java com o seguinte conteúdo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class CadastraServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); String nome = request.getParameter(“nome”); String sexo = request.getParameter(“sexo”); String email = request.getParameter(“email”); saida.println(“<html>”); saida.println(“<body>”); saida.println(“<form action=’curso’ method=’post’> ”); saida.println(“Curso: <select name=curso>”); saida.println(“<option value=’Violão’>Violão</option>”); saida.println(“ <option value=’Piano’>Piano</option>”); saida.println(“ <option value=’Baixo’>Baixo</option>”); saida.println(“ <option value=’Bateria’>Bateria</option>”); saida.println(“</select><p/>”); saida.println(“<input type=’submit’ value=’Enviar’/> ”); saida.println(“</form> ”); saida.println(“</body>”); saida.println(“</html>”); } } 240 Linguagens de Programação II.indb 240 7/12/2006 14:01:08 Linguagens de Programação II 3) Dentro do diretório src crie um novo arquivo chamado CursoServlet.java com o conteúdo abaixo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class CursoServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); String curso = request.getParameter(“curso”); saida.println(“<html>”); saida.println(“<body>”); saida.println(“SUA INSCRIÇÃO NO CURSO FOI FINALIZADA <br/>”); saida.println(“<a href=’index.html’>Voltar a tela principal</a>”); saida.println(“</body>”); saida.println(“</html>”); } } 4) Crie um arquivo chamado index.html com o conteúdo abaixo e o salve na pasta raiz da aplicação, ou seja, na pasta aplicacaoWeb: <html> <body> <form action=”cadastro” method=”post”> Nome: <input type=”text” name=”nome” /><p /> Email: <input type=”text” name=”email” /> <p /> Sexo: <select name=”sexo”> <option value=”Masculino”>Masculino</option> <option value=”Feminino”>Feminino</option> </select><p/> <input type=”submit” value=”Enviar”/> </form> </body> </html> Unidade 12 Linguagens de Programação II.indb 241 241 7/12/2006 14:01:09 Universidade do Sul de Santa Catarina 5) Crie um arquivo chamado web.xml, esse arquivo será o deployment descriptor, dentro do diretório WEB-INF com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> <servlet> <servlet-name>Cadastra Aluno</servlet-name> <servlet-class>CadastraServlet</servlet-class> </servlet> <servlet> <servlet-name>Curso Aluno</servlet-name> <servlet-class>CursoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Cadastra Aluno</servlet-name> <url-pattern>/cadastro</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Curso Aluno</servlet-name> <url-pattern>/curso</url-pattern> </servlet-mapping> </web-app> 6) Agora compile os Servlets. Para isso, abra o console de windows e vá até o diretório da sua raiz aplicação e digite o comando: javac –classpath $catalina_home/common/lib/servlet-api.jar –d WEB-INF/classes src/*.java Atenção! Lembre-se de dois pontos: o comando deve estar numa linha apenas e substitua $catalina_home pelo diretório onde está localizado o Tomcat. O caminho inteiro do diretório deve estar entre aspas duplas. 242 Linguagens de Programação II.indb 242 7/12/2006 14:01:09 Linguagens de Programação II 7) Copie o diretório aplicacaoWeb para o diretório $catalina_home/webapps 8) Reinicie o Tomcat. Digite no browser o endereço http://localhost:8080/ sistemaCadastro/index.html e você conseguirá navegar entre as páginas de cadastro dos dados básicos, a página de seleção do curso e a página de confirmação da inscrição em um determinado curso. Porém, note que em nenhum momento são guardadas as informações do usuário. Na próxima seção, você aprenderá a ver como contornar essa situação, ao se trabalhar com sessão. A seqüência de telas mostra a aplicação em execução. Figura 12.7 – Primeiro formulário de entrada de dados Figura 12.8 – Segundo formulário de entrada de dados Figura 12.9 – Tela de finalização da aplicação Unidade 12 Linguagens de Programação II.indb 243 243 7/12/2006 14:01:09 Universidade do Sul de Santa Catarina Seção 4 - Sessões No exemplo anterior, você viu como estabelecer vínculos entre os Servlets. Porém, um novo problema foi enfrentado, pois não se conseguiu manter as informações do aluno no sistema. No momento, a intenção é manter essas informações sem ter que armazenar em um banco de dados, até por que o aluno pode não querer finalizar a inscrição e dessa formar poderíamos começar a inserir alunos, na base de dados, que não seriam alunos de fato. Agora, você modificará o exemplo anterior para trabalhar com sessão e dessa forma conseguir manter o estado do candidato até o final do processo de inscrição. Para modificar siga os seguintes passos: 1) Crie na pasta src do projeto sistemaCadastra uma classe Java chamada Candidato.java com o seguinte conteúdo: public class Candidato { private String nome; private String email; private String sexo; private String curso; public Candidato() { } public void setNome(String nome){ this.nome = nome; } public void setEmail(String email){ this.email = email; } public void setSexo(String sexo){ this.sexo = sexo; } public void setCurso(String Curso){ this.curso = curso; } public String getNome (){ return this.nome; } public String getEmail (){ return this.email; } public String getSexo (){ return this.sexo; } public String getCurso (){ return this.curso; } } 244 Linguagens de Programação II.indb 244 7/12/2006 14:01:09 Linguagens de Programação II 2) Dentro do diretório src modifique o arquivo chamado CadastroServlet.java com o seguinte conteúdo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class CadastraServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); String nome = request.getParameter(“nome”); String sexo = request.getParameter(“sexo”); String email = request.getParameter(“email”); Candidato candidato = new Candidato(); candidato.setNome(nome); candidato.setEmail(email); candidato.setSexo(sexo); HttpSession sessao = request.getSession(); sessao.setAttribute(“candidato”, candidato); saida.println(“<html>”); saida.println(“<body>”); saida.println(“<form action=’curso’ method=’post’> ”); saida.println(“Curso: <select name=curso>”); saida.println(“<option value=’Violão’>Violão</option>”); saida.println(“ <option value=’Piano’>Piano</option>”); saida.println(“ <option value=’Baixo’>Baixo</option>”); saida.println(“ <option value=’Bateria’>Bateria</option>”); saida.println(“</select><p/>”); saida.println(“<input type=’submit’ value=’Enviar’/> ”); saida.println(“</form> ”); saida.println(“</body>”); saida.println(“</html>”); } } Unidade 12 Linguagens de Programação II.indb 245 245 7/12/2006 14:01:10 Universidade do Sul de Santa Catarina 3) Dentro do diretório src modifique o arquivo chamado CursoServlet.java com o conteúdo abaixo: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class CursoServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter saida = response.getWriter(); String curso = request.getParameter(“curso”); HttpSession sessao = request.getSession(); Candidato candidato = (Candidato) sessao.getAttribute(“candidato”); candidato.setCurso(curso); saida.println(“<html>”); saida.println(“<body>”); saida.println(“SUA INSCRIÇÃO NO CURSO FOI FINALIZADA <br/>”); saida.println(“Os seus dados são <br/>”); saida.println(“Nome: ” + candidato.getNome() + “<br/>”); saida.println(“Sexo: ” + candidato.getSexo()+ “<br/>”); saida.println(“Email: ” + candidato.getEmail()+ “<br/>”); saida.println(“Curso: ” + candidato.getCurso()+ “<br/>”); saida.println(“<a href=’index.html’>Voltar a tela principal</a>”); saida.println(“</body>”); saida.println(“</html>”); } } 4) Agora compile novamente os Servlets. Para isso, abra o console de windows e vá até o diretório da sua raiz aplicação e digite o comando: javac –classpath $catalina_home/common/lib/servlet-api.jar –d WEB-INF/classes src/*.java Atenção! Lembre-se de dois pontos: o comando deve estar numa linha apenas e substitua $catalina_home pelo diretório onde está localizado o Tomcat. 246 Linguagens de Programação II.indb 246 7/12/2006 14:01:10 Linguagens de Programação II 5) Copie o diretório aplicacaoWeb para o diretório $catalina_home/webapps 6) Reinicie o Tomcat. Abra o browser e digite o endereço http://localhost:8080/sistemaCadastro/index.html. Você fará o processo de inscrição normalmente como da primeira vez. Porém, na última página, em que será mostrada a tela confirmando a sua inscrição, seus dados serão informados, como na figura 12.8 a seguir: FIGURA 12.10 – PÁGINA DE RESULTADO DO PROCESSO DE INSCRIÇÃO Veja que é possível manter o estado de um usuário do sistema por meio da nova interface que apareceu no exemplo javax.servlet. http.HttpSession. Esta interface é uma alternativa aos outros métodos (cookies, reescrita de url, etc.) de armazenar informações do usuário. Ela fornece uma API mais poderosa e fácil de trabalhar do que os outros métodos. Perceba que uma sessão está sempre associada a uma requisição (request.getSession()), pois quem faz a requisição é o usuário e como se quer manter o estado do usuário, não tem lugar melhor para encontrar informações do usuário do que na requisição. De posse da sessão do usuário é possível manipulá-la normalmente utilizando o método setAttribute(nomeAtributo, valorAtributo) para poder adicionar na sessão os nossos objetos, sempre utilizando a dupla nome-valor, ou seja, adicionando na sessão um objeto com um determinado rótulo. No exemplo, isso foi feito com o candidato, pois adicionamos na sessão um candidato com o rótulo “candidato”. Unidade 12 Linguagens de Programação II.indb 247 247 7/12/2006 14:01:10 Universidade do Sul de Santa Catarina No Servlet seguinte recuperamos a informação desse candidato apenas passando o rótulo do objeto que tínhamos informado anteriormente. Dessa forma, a recuperação de objetos na sessão ocorre por meio do método getAttribute(nomeAtributo). Atenção! Sempre que você for recuperar algum objeto da sessão você deve fazer o typecast para o determinado objeto, pois a sessão sempre retornará um Object caso você não faça a conversão. A sessão é uma funcionalidade muito importante da especificação dos Servlets e é muito útil no desenvolvimento de aplicações web. Porém, deve ser utilizada com cuidado, pois para cada objeto que se adiciona na sessão, uma área de memória é ocupada com esse objeto. Dessa forma, se for adicionado tudo que é objeto na sessão chagará um momento em que o consumo de memória será alto devido a esse descuido. A interface javax.servlet.http. HttpSession possui uma série de métodos e é recomendado que você estude esses métodos para a melhor utilização desse recurso. Uma coisa neste capítulo pode ter deixado você preocupado: “Mas eu vou ter sempre que escrever o conteúdo das minhas páginas dentro de um Servlet?”. Desenvolver uma aplicação dessa forma não seria uma boa prática, pois sua aplicação estaria toda amarrada dentro de alguns Servlets. Pensando nisso, foram criadas as Java Server Pages (JSP), com a proposta de retirar de dentro dos Servlets o conteúdo das páginas, que é, justamente, o assunto que você estudará na próxima unidade. 248 Linguagens de Programação II.indb 248 7/12/2006 14:01:10 Linguagens de Programação II Síntese Nessa unidade vimos os conceitos que fazem parte da especificação dos Servlets, como deve ser a estrutura de uma aplicação web, as formas que uma aplicação web recebe dados enviados pelo usuário, por meio de formulários, como a aplicação pode estar gerando informações dinâmicas e enviando-as ao usuário. Por fim, você viu um item importante nas especificação dos Servlets que é utilizado em 99% das aplicações web, as sessões que de uma forma simples é como o Servlet Container mantêm o estado do usuário no servidor. A tecnologia dos servlets é fundamental para o desenvolvimento de aplicações web que utilizam Java, pois ela é a base para a maioria das soluções, tanto comerciais quanto livres, que estão disponíveis no mercado. Atividades de auto-avaliação Leia com atenção os enunciados seguintes e resolva as atividades programadas para a sua auto-avaliação. 1) Quais métodos devem estar sendo implementados nos Servlets para que eles possam funcionar corretamente? 2) Como é feito o mapeamento dos Servlets para que eles possam ser chamados a partir de uma requisição do nevagador? 3) Quais as classes são responsáveis por enviar os dados do cliente ao servidor e enviar dados do servidor para o cliente? 4) Desenvolva uma aplicação web que funcione como uma agenda de contatos, ou seja, você irá cadastrar: nome, email e telefone dos seus contatos. Unidade 12 Linguagens de Programação II.indb 249 249 7/12/2006 14:01:10 Universidade do Sul de Santa Catarina Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: HALL, Marty. Core Servlets and JavaServer Pages. [S. l.]: Prentice Hall, [200?]. HALL, Marty. More Servlets and JavaServer Pages. [S. l.]: Pearson Education, [200?]. FIELDS, Duane; KOLB, Mark; Web development with Java Server Pages. [S. l.]: Manning Publications, 2000. SIERRA, Kathy; BASHMAN, Brian; BATES, Bert. Head first Servlets and JSP. [S. l.]: O’Reilly, 2004. http://servlets.com/ (Site com muito material sobre a tecnologia Java Servlets) 250 Linguagens de Programação II.indb 250 7/12/2006 14:01:10 UNIDADE 13 Java Server Pages (JSP) Objetivos de aprendizagem Entender como funcionam as páginas JSP. Conhecer os recursos oferecidos pela tecnologia JSP. Desenvolver aplicações com páginas JSP dinâmicas. Seções de estudo Seção 1 Java Server Pages Seção 2 Sintaxe e Semântica Linguagens de Programação II.indb 251 7/12/2006 14:01:10 Universidade do Sul de Santa Catarina Para início de conversa Após termos visto a tecnologia dos Java Servlets, veremos uma tecnologia complementar que irá tornar o desenvolvimento de aplicações web em Java muito mais fácil e rápido. Esta tecnologia é o Java Server Pages (JSP) e iremos verificar como são as páginas JSP, como elas funcionam, sua sintaxe e semântica além de verificar exemplos de sua utilização. SEÇÃO 1 – Java Server Pages Após verificar que o desenvolvimento de aplicações web utilizando Servlets seria muito trabalhoso e não seria uma boa prática - pois todo o conteúdo de apresentação estaria amarrado em Servles - a Sun criou a especificação Java Server Pages (JSP). Os JSP são páginas dinâmicas semelhantes a páginas PHP e ASP e elas permitem que seja inserido código Java dentro delas, facilitando assim o desenvolvimento de aplicações web. Quando você desenvolve uma aplicação utilizando JSP, não é preciso se preocupar com a compilação como é feito com Servlets. Apenas desenvolva o JSP’s e coloque na aplicação, e o Servlet Container fará todo o resto do trabalho. Veja seguir uma aplicação de exemplo onde será exibida uma mensagem “Hello World” na tela, com uma página JSP: 1) Crie novamente a seguinte estrutura de diretórios para a aplicação: sistemaJSP |-src |-WEB-INF |-classes 252 Linguagens de Programação II.indb 252 7/12/2006 14:01:11 Linguagens de Programação II 2) Dentro do diretório sistemaJSP, crie um arquivo chamado helloWorld.jsp com o seguinte conteúdo: <html> <head> <title>Hello World</title> </head> <body> Hello World <br/> O resultado da soma 2 + 2 é <%=2 + 2%> </body> </html> 3) Crie dentro do diretório WEB-INF o arquivo web.xml com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> </web-app> 4) Copie o diretório aplicacaoWeb para o diretório $catalina_home/webapps 5) Reinicie o Tomcat, abra o browser e digitehttp:// localhost:8080/sistemaJSP/helloWorld.jsp. Você verá algo semelhante a figura a seguir: FIGURA 13.1 – VISUALIZANDO A MENSAGEM HELLO WORLD Você pode ver, por esse exemplo, que não é preciso utilizar algumas coisas que se utilizava com os Servlets: não é preciso criar classes Java, o nosso descritor da aplicação estava vazio; não é preciso ficar escrevendo cada uma dos nossos JSP’s e a página JSP foi capaz de executar o código que estava contido entre as Unidade 13 Linguagens de Programação II.indb 253 253 7/12/2006 14:01:11 Universidade do Sul de Santa Catarina tags de abertura “<%” e de fechamento “%>”. Em outras palavras, desenvolvemos uma pequena aplicação de maneira muito rápida. Vamos agora incrementar uma pouco mais a nossa aplicação permitindo a ela exibir o dia corrente através de uma classe bastante conhecida nossa, a classe Date. Para podermos utilizar essa classe na nossa página JSP precisamos fazer algo semelhante ao que fazemos quando desenvolvemos uma classe Java normal: precisamos importar a classe para poder utilizá-la. No nosso caso é a classe Date que deverá ser importada. Modificando a nossa página JSP da seguinte forma, poderemos utilizar a classe Date sem problema: <%@ page import=”java.util.Date” %> <html> <head> <title>Hello World</title> </head> <body> Hello World <br/> Hoje é <%=new Date()%> </body> </html> O que nós utilizamos, no exemplo anterior, para poder informar que iríamos fazer um import da classe Date foi um recurso muito útil do JSP, conhecido como diretiva. A diretiva page possui vários atributos, o import é apenas uma deles, existem mais atributos que podem estar sendo utilizados na diretiva page. 254 Linguagens de Programação II.indb 254 7/12/2006 14:01:11 Linguagens de Programação II Verifique no quadro a seguir alguns atributos da diretiva page: Atributos Descrição language Define a linguagem de script que será utilizada no JSP. A única lingaguem suportada é Java. extends Define o nome da classe que essa página JSP deve herdar. Geralmente esse atributo não é informado, é deixado a cargo do Servlet Container se preocupar com isso. import Permite a página JSP fazer import de pacotes e classes que serão utilizadas. session Define se a página em questão deve fazer parte de uma sessão. O valor default é true. buffer Define o tamanho do buffer da página JSP em kilobytes, caso não seja definido a saída não será buferizada. autoFlush Se o valor desse atributo for true, o buffer da página JSP será finalizado caso ele tenha atingido o seu limite. isThreadSafe Se o valor desse atributo for false, a página JSP não irá implementar a interface SingleThreadModel. O valor default é true. info Retorna o resultado do método getServletInfo() da classe que implementa essa página JSP. errorPage Define o caminho relativo a uma página de erro, caso uma exceção seja lançada. contentType Informa o tipo de saída do documento. O valor default é text/html. isErrorPage Informa se a página é uma página de erro. pageEncoding Define o caracter encoding da página. Além da diretiva page, existem outras duas diretivas: a taglib que estaremos vendo na próxima unidade sobre JSTL e a diretiva include, que permite incluir em uma página JSP textos e códigos que serão utilizados no momento de execução das páginas JSP. Isso permite construir pedaços de páginas reutilizáveis (como cabeçalhos, rodapés, barra de navegação, etc). Unidade 13 Linguagens de Programação II.indb 255 255 7/12/2006 14:01:11 Universidade do Sul de Santa Catarina A sintaxe da utilização da diretiva include é a seguinte: <html> <head> <title>Hello World</title> </head> <body> <%@ include file=”cabecalho.jsp” %> Hello World <br/> Hoje é <%=new Date()%> </body> </html> No exemplo apresentado, quando o Servlet Container encontrar a diretiva include, ele irá colocar no ponto onde ele encontrou a diretiva o conteúdo da página “cabecalho.jsp”. A especificação JSP cobre muitas outras situações através de mecanismos que possibilitam uma melhor utilização das páginas JSP são eles: declarações JSP, Expressões JSP e Scriptlets. Veremos cada um deles a seguir. SEÇÃO 2 – Sintaxe e Semântica As declarações JSP são utilizadas para fazer declarações de métodos e atributos em uma página JSP. Imagine um cenário onde você quer fazer uma contagem de acessos a uma determinada página JSP, ou seja, a cada acesso a uma determinada página é incrementado o valor. Poderíamos utilizar uma declaração JSP para fazer declaração de um atributo contador e incrementá-lo a cada acesso como no código mostrado abaixo, lembrando que para utilizarmos uma declaração em JSP devemos utilizar a seguinte sintaxe: <%! Conteúdo a ser declarado %> 256 Linguagens de Programação II.indb 256 7/12/2006 14:01:12 Linguagens de Programação II Exemplo: <html> <head> <title>Contador</title> </head> <body> <%! int count=0; %> Esta página foi teve <%= ++count%> acessos. </body> </html> Expressões JSP No exemplo anterior utilizamos uma expressão após termos incrementado o valor do contador. Fizemos isso, pois, além de efetuarmos o incremento, nós queríamos disponibilizar esse valor ao usuário. É justamente essa a função de uma expressão JSP: atribuir um determinado valor na página JSP. Utilizamos uma expressão JSP com a seguinte sintaxe: <%= Conteúdo a ser expresso, ou seja, atribuído a página %> Exemplo: <html> <head> <title>Contador</title> </head> <body> <%! int count=0; %> Esta página foi teve <%= ++count%> acessos. </body> </html> Unidade 13 Linguagens de Programação II.indb 257 257 7/12/2006 14:01:12 Universidade do Sul de Santa Catarina Scriptlet Os scriptlets são um dos melhores recursos fornecidos pela especificação JSP, porém um dos mais perigosos de se utilizar, pois pode viciar o programador a sempre utilizar scriptlets. Um scriptlet é uma funcionalidade que permite ao programador embutir código Java dentro de uma página JSP, a sintaxe e um exemplo de utilização serão mostrados a seguir: <% Qualquer código Java é permitido entre essas marcações %> Exemplo: <html> <head> <title>Scriptlet</title> </head> <body> <% String nome = “Tom Jobim”; int quantidade = nome.lenght(); %> O nome digitado foi <%= nome%> e ele possui <%= quantidade%> letras. </body> </html> Você viu que as páginas JSP podem utilizar os recursos de diretivas, declarações, expressões e scriptlets, porém a especificação ainda possui mais um mecanismo que aumenta a funcionalidade das páginas JSP, são os chamados objetos implícitos. Esses objetos recebem o nome de implícitos pois não precisam ser instanciados para ser utilizados, e eles podem ser acessados diretamente. Os objetos implícitos que podem ser acessados em uma página JSP são: 258 Linguagens de Programação II.indb 258 7/12/2006 14:01:12 Linguagens de Programação II out Este objeto é do tipo Writer, ou seja, tudo que for escrito nesse objeto, por meio do método print, será exibido na página. request Este objeto permite que você tenha acesso aos parâmetros enviados pelo cliente, ao método HTTP utilizado (GET ou POST), etc. response Objeto que permite o acesso a resposta que será enviada ao usuário. session Objeto que possui uma referência à sessão associada com a requisição feita pelo usuário. application Objeto que referencia a classe ServletContext e permite que sejam armazenados valores que serão compartilhados por toda aplicação, por meio dos métodos setAttribute e getAttribute. config Objeto utilizado para a leitura de parâmetros de inicialização. exception Permite que páginas JSP sejam definidas como páginas de erro. pageContext Objeto que é um ponto de acesso a muitos atributos da página em questão, ou seja, por meio dele você poderá ter acesso aos objetos out, request, response, etc. page Objeto semelhante à referência this utilizada em classes Java comuns. Veja agora o exemplo de uma aplicação onde será utilizado a maioria dos recursos apresentados anteriormente. 1) Crie a seguinte estrutura de diretórios para a aplicação: sistemaExibe |-src |-paginas |-WEB-INF |-classes 2 )Dentro do diretório paginas crie os seguintes arquivos: Unidade 13 Linguagens de Programação II.indb 259 259 7/12/2006 14:01:12 Universidade do Sul de Santa Catarina cabecalho.jsp <h1>Aplicação JSP</h1> Esta é uma demonstração da utilização dos varios recursos que JSP possui<br/> conteudo.jsp <%@ page import=”java.util.Date” %> <%@ page import=”java.text.SimpleDateFormat” %> <html> <head> <title>Java Server Pages</title> </head> <body> <%@ include file=”cabecalho.jsp” %> <form action=”recuperaInformacoes.jsp” method=”post”> Nome: <input type=”text” name=”nome”/><br/> Data de Nascimento: <input type=”text” name=”dtaNascimento”/> <input type=”submit” value=”Enviar”/> </form> <%@ include file=”rodape.jsp” %> </body> </html> recuperaInformacoes.jsp <%@ page import=”java.util.Date” %> <%@ page import=”java.text.SimpleDateFormat” %> <html> <head> <title>Java Server Pages</title> </head> <body> <%@ include file=”cabecalho.jsp” %> Você informou os seguintes dados: <br/> Nome : <%=request.getParameter(“nome”) %> <br/> Data de Nascimento: <%=request.getParameter(“dtaNascimento”) %> <br/> <%@ include file=”rodape.jsp” %> </body> </html> 260 Linguagens de Programação II.indb 260 7/12/2006 14:01:12 Linguagens de Programação II rodape.jsp <h1>Hoje é <%= new SimpleDateFormat(“dd/mm/yyyy”).format(new Date())%></h1> 3) Crie dentro do diretório WEB-INF o arquivo web.xml com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> </web-app> 4) Copie o diretório sistemaExibe para o diretório $catalina_home/webapps 5) Reinicie o Tomcat, abra o browser e digite http:// localhost:8080/sistemaExibe/paginas/conteudo.jsp. Você verá algo semelhante a figura abaixo: FIGURA 13.2 - PÁGINA PRINCIPAL Após preencher os dados e clicar no botão “enviar” você verá algo semelhante à tela a seguir: FIGURA 13.3 - TELA DE RESULTADO Unidade 13 Linguagens de Programação II.indb 261 261 7/12/2006 14:01:12 Universidade do Sul de Santa Catarina Você pode perceber no exemplo que utilizamos o recurso das diretivas page e include que utilizamos o acesso a um dos objetos implícitos no momento em que recuperamos os parâmetros chamando request.getParameter. Utilizamos também expressões quando criamos uma data, formatamos e a atribuímos na página. Assim como esses recursos, todos os apresentados anteriormente podem ser utilizados no desenvolvimento de aplicações que utilizem JSP. Por fim, você verá a utilização de mais um recurso em páginas JSP. Para isso, visualize o seguinte exemplo: imagine que nós temos as classes do nosso sistema prontas, por exemplo a classe Pessoa. O que vimos até o momento não nos permite utilizar essa classe, portanto, a saída para isso é a utilização das Ações JSP, que permitem ter acesso a Java Beans que já desenvolvemos e utilizamos. Veja a seguir a sintaxe e utilização da mesma: <jsp:useBean id=”nome” scope=”page | request | session | application” class=”className” type=”typeName” | bean=”beanName” type=”typeName” | type=”typeName” /> Exemplo: <jsp:useBean id=”pessoa” class=”br.unisul.Pessoa” scope=”request” /> <html> <head> <title>useBean</title> </head> <body> O nome da pessoa é <%=pessoa.getNome()%>. </body> </html> 262 Linguagens de Programação II.indb 262 7/12/2006 14:01:13 Linguagens de Programação II Além de poder estar referenciando um Java Bean em uma página JSP você pode estar alterando o estado dele através das tags jsp: getProperty e jsp:setProperty, veja dois exemplos para o Java Bean utilizado anteriormente: Exemplo: <jsp:useBean id=”pessoa” class=”br.unisul.Pessoa” scope=”request” /> <html> <head> <title>useBean</title> </head> <body> O nome da pessoa é <jsp:getProperty name=”pessoa” property=”nome”/>. <br/> Alterando o nome da Pessoa <jsp:setProperty name=”pessoa” property=”nome” value=”novoNome”/> </br> O novo nome da pessoa é <jsp:getProperty name=”pessoa” property=”nome”/>. </body> </html> Tendo visto esses elementos, você está apto a começar o desenvolvimento de aplicações web utilizando a tecnologia Java Server Pages, a espeficicação possui ainda uma série de itens que você deve conhecer para se aprofundar na tecnologia. Java Server Pages é utilizado hoje em muitos sistemas desenvolvidos em Java e com certeza o conhecimento desta tecnologia é imprescindível. Na próxima unidade veremos como estar melhorando ainda mais o desenvolvimento de aplicações Java para web. Unidade 13 Linguagens de Programação II.indb 263 263 7/12/2006 14:01:13 Universidade do Sul de Santa Catarina Síntese Você viu neste capítulo como é fácil desenvolver aplicações web utilizando JSP. Porém essa facilidade apresentada pelo JSP pode acabar se tornando um pesadelo, caso utilizemos de forma errada os recursos oferecidos por ela. Quando programávamos utilizando Servlets, caímos no ciclo de estarmos desenvolvendo páginas HTML dentro dos Servlets. Agora fomos pro lado oposto, ou seja, podemos correr o risco de trazer a programação dos Servlets para dentro de uma página JSP. O que não vimos ainda é que na verdade uma página JSP é um Servlet, pois mesmo ela sendo uma página, ela será compilada e executada como um Servlet, porém essa tecnologia foi criada como o intuito de atuar na camada de visão, ou seja, ela deve apenas exibir e fornecer os dados para a aplicação. Você verá no próximo capítulo como estar aliando os dois mundos Servlets e JSP da melhor forma possível utilizando o JSTL. 264 Linguagens de Programação II.indb 264 7/12/2006 14:01:13 Linguagens de Programação II Atividades de auto-avaliação Leia com atenção os enunciados seguintes e resolva as atividades programadas para a sua auto-avaliação. 1) Qual a sintaxe de declarações, expressões e scriptlets em JSP? 2) Qual a relação entre Servlets e JSP? 3) Como podemos utilizar em JavaBean nas páginas JSP? Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: FALKNER, Jason. JONES, Kevin. Servlets and Java Server Pages: the J2EE technology web tier. [S. l.]: Addison-Wesley, 2003. KURNIAWAN, Budi. Java for web with Servlets, JSP and EJB: a developer’s guide to J2EE solutions. [S. l.]: New Riders, 2002 http://java.sun.com/products/jsp/ (Site da especificação Java Server Pages (JSP)) Unidade 13 Linguagens de Programação II.indb 265 265 7/12/2006 14:01:13 Linguagens de Programação II.indb 266 7/12/2006 14:01:13 UNIDADE 14 Java Standard Tag Library (JSTL) Objetivos de aprendizagem Criar páginas JSP de maneira mais fácil. Facilitar a interação entre desenvolvedores e designers. Permitir a reutilização dos componentes da biblioteca JSTL. Seções de estudo Seção 1 JSTL Seção 2 Instalação Seção 3 Linguagem de Expressão JSTL Seção 4 Bibliotecas JSTL Linguagens de Programação II.indb 267 7/12/2006 14:01:13 Universidade do Sul de Santa Catarina Para início de conversa Veremos nesta unidade como estar desenvolvendo aplicações web de forma produtiva, pois iremos conhecer uma biblioteca que facilita o desenvolvimento de páginas JSP, permitindo que essa biblioteca seja reutilizada em todo o projeto e, conseqüentemente, facilitando a interação entre a equipe de desenvolvimento e de designer. Seção 1 - JSTL A Java Standard Tag Library (JSTL), foi um movimento para a especificação de uma biblioteca padrão de tags para: iteração, avaliação condicional e tags que utilizam linguagens de expressão, além de prover acesso simplificado aos atributos dos objetos PageContext, HttpServletRequest, HttpSession e ServletContext. Mas por que isso? Na unidade anterior, você viu que se pode inserir código Java diretamente nas nossas páginas JSP. Porém, essa não é uma prática recomendável, principalmente por dificultar uma posterior manutenção. Dessa forma, os desenvolvedores começaram a desenvolver bibliotecas próprias que executavam o código Java, mas utilizavam uma notação HTML na página JSP. Assim eles reutilizavam bastante código e não espalhavam o código Java nas páginas JSP. Porém, notou-se que cada desenvolvedor desenvolvia a sua biblioteca própria. Dessa forma, estabeleceu-se uma especificação para padronizar essas bibliotecas e então surgiu o JSTL. 268 Linguagens de Programação II.indb 268 7/12/2006 14:01:13 Linguagens de Programação II Seção 2 - Instalação Para poder utilizar as bibliotecas JSTL, é preciso baixá-las e instalá-las. Utilize a versão 1.1 das bibliotecas do projeto Apache Jakarta que está localizada no site: http://ftp.unicamp. br/pub/apache/jakarta/taglibs/standard/binaries/ jakarta-taglibs-standard-1.1.2.zip Após ter efetuado o download do arquivo, o descompacte em um diretório qualquer (exemplo: C:/). Alguns arquivos e diretórios, do arquivo baixado, são apresentados abaixo: README Arquivo que contém uma breve descrição de cada biblioteca inclusa na distribuição. lib Diretório que contém todos os jars necessários para utilização do JSTL. tld Diretório que contém uma cópia de cada arquivo TLD requerido para cada biblioteca JSTL. standard-docs.war Arquivo que contém a documentação básica do JSTL. standard-examples.war Arquivo que contém exemplos de utilização do JSTL. Para você utilizar JSTL nas nossas aplicações, o que se precisa fazer é copiar os arquivos standard.jar e jstl.jar para o diretório WEB-INF/lib das nossas aplicações e adicionar a diretiva taglib no início das páginas onde formos utilizar as tags da seguinte forma: <%@ taglib prefi x=”c” uri=”http://java.sun.com/jstl/core”. Unidade 14 Linguagens de Programação II.indb 269 269 7/12/2006 14:01:14 Universidade do Sul de Santa Catarina No caso, foi exemplificado com a biblioteca core, porém os valores de prefi xo e uri podem ser: Prefixo Uri c http://java.sun.com/jstl/core sql http://java.sun.com/jstl/sql x http://java.sun.com/jstl/xml fmt http://java.sun.com/jstl/fmt Dessa forma, a instalação do JSTL está pronta e é preciso apenas informar nas nossas páginas JSP que iremos utilizá-la, mas isso você verá mais adiante. Agora você estudará um pouco o que significa linguagem de expressão. Seção 3 - Linguagem de Expressão JSTL Uma das principais características do JSTL, quando foi lançada a versão 1.0, foi a adição das linguagens de expressão (EL), ou seja, era uma forma mais fácil de se referenciar objetos nas páginas JSP. Quando você utilizar EL, os objetos serão acessados da seguinte forma ${nomeDoObjeto}. Você também pode acessar os atributos do objeto, porém modificando um pouco a utilização anterior, com a seguinte sintaxe ${nomeDoObjeto.nomeDoAtributo}. A utilização de EL facilita muita o trabalho do desenvolvedor, pois quando se está acessando o atributo de um objeto, por exemplo, não é preciso se preocupar se esse atributo irá retornar um valor nulo ou não, pois a EL trata isso. Assim, não se corre o risco de receber um NullPointerException na nossa página JSP, pois nesse caso será retornado uma String com o valor vazio. A seguir você estudará as bibliotecas JSTL. 270 Linguagens de Programação II.indb 270 7/12/2006 14:01:14 Linguagens de Programação II Seção 4 - Bibliotecas JSTL As bibliotecas JSTL são divididas em quatro grupos, porém você utilizará apenas a biblioteca Core. Abaixo são listadas todas as bibliotecas: Core Fornece tags para a realização de tarefas básicas como manipulação de objetos, tratamento de exceções, fluxo condicional, iterações e manipulação de URLs. SQL Fornece tags para a manipulação básica de banco de dados. XML Fornece tags para a manipulação de elementos XML, controle de fluxo baseado em expressões Xpath e transformações de documentos XML aplicando XSLT. FMT Possui tags para internacionalização de mensagens, além da formatação de datas, horários, valores monetários. Aprofunde seu estudo da JSTL com a tag mais básica da biblioteca Core. <c:out> - Essa tag avalia uma expressão e exibe o resultado na página. A expressão que será avaliada está definida no atributo value. Caso o resultado da avaliação seja null é impresso uma String vazia. Pode-se também especificar um valor padrão para evitar esses casos através do atributo default. Veja a seguir exemplos de utilização e do resultado proporcionado pela tag: Utilização Resultado <c:out value=”texto”/> Texto. <c:out value=”${usuario.nome}” default=”convidado”/> Caso a expressão usuario.nome seja nula, será impresso convidado. <html> <body> <c:out value=”Texto a ser impresso”/> </body> </html> Texto a ser impresso. Unidade 14 Linguagens de Programação II.indb 271 271 7/12/2006 14:01:14 Universidade do Sul de Santa Catarina <c:set> - Permite definir um valor de uma variável de um escopo ou de uma propriedade. Quando for utilizar variáveis de escopo, deve-se utilizar o atributo var para o nome da variável, scope para o escopo e value para o valor. Para definir propriedades de um objeto os seguintes atributos devem ser preenchidos: target para indicar o objeto, property para indicar a propriedade e value para especificar o valor. Veja os exemplos a seguir: Utilização Resultado <c:set var=”nome” scope=”request” value=”Monteiro Lobato”/> Será atribuído o valor Monteiro Lobato à variável nome. <c:set target=”pessoa” property=”nome” value=”Monteiro Lobato”/> Será atribuído ao atributo nome da pessoa o valor Monteiro Lobato. <html> <body> <c:set var=”texto” scope=”request” value=”Texto a ser impresso”/> <c:out value=”${texto}”/> </body> </html> Texto a ser impresso. <c:remove> - Remove uma variável de um determinado escopo. O nome da variável a ser excluída é especificado no atributo var e o escopo no atributo scope. Veja os exemplos: Utilização Resultado <c:remove var=”nome” scope=”request”/> Será removida a variável nome do request. <html> <body> <c:remove var=”nome” scope=”request”/> </body> </html> Variável nome removida do escopo request. 272 Linguagens de Programação II.indb 272 7/12/2006 14:01:14 Linguagens de Programação II <c:catch> - Captura uma exceção ocorrida no corpo da tag e atribui o valor a exceção ao atributo var. Essa tag tem o objetivo de tratar erros menores, onde não é necessário um tratamento detalhado do erro. Acompanhe os exemplos: Utilização Resultado <c:catch var=”excecao”/> Caso seja lançada uma exceção, será colocada na variável excecao. <html> <body> <c:catch var=”excecao”> <!-- irá gerar uma exceção pois a classe pessoa não possui o atributo Identificador --> <c:set target=”pessoa” property=”Identificador” value=”321654”/> </c:catch> Exceção: <c:out value=”${excecao}”/> </body> </html> Lançará uma exceção, colocará a exceção na variável excecao e irá imprimir a exceção pela tag <c: out/>. <c:if> - Executa o corpo da tag apenas se uma expressão for verdadeira. A expressão a ser avaliada é definida pelo atributo test. Pode-se ainda atribuir o resultado da expressão a uma variável informada no atributo var. Veja os exemplos: Utilização Resultado <c:if test=”${pessoa.idade == 18}” var=”maior”/> Verifica se a idade da pessoa é igual a 18 anos e atribui o resultado dessa verificação a variável maior. <html> <body> <c:if test=”${pessoa.id == 1}” > Se for a pessoa com Id igual a 1 acessando essa página, então ela verá esse texto </c:if> </body> </html> Irá verificar o id da pessoa e caso ele seja igual a 1 a pessoa verá o texto inserido dentro da tag <c:if>. Unidade 14 Linguagens de Programação II.indb 273 273 7/12/2006 14:01:14 Universidade do Sul de Santa Catarina <c:choose> - Executa um elemento interno quando este elemento interno for verdadeiro. Esta tag é utilizada para verificar múltiplas condições. Cada condição deve ser verificada pela tag interna <c: when>, ela possui um atributo test onde será feita a avaliação da expressão de forma semelhante a tag <c:if>. Pode-se também utilizar uma tag <c:otherwise> para ser o que será executado caso nenhuma das condições das tags <c:when> for atendida. Veja os exemplos: Utilização Resultado <c:choose> <c:when test=”${pessoa.idade >= 18}”> <c:out value=”maior de idade”/> </c:when> <c:otherwise> <c:out value=”menor de idade”/> </ c:otherwise> </c:choose> Caso a idade da pessoa é igual ou maior a 18 anos imprime o resultado maior de idade, senão imprime menor de idade. <html> <body> <c:choose> <c:when test=”${cor == ‘Azul’}”> <c:out value=”a cor escolhida foi azul”/> </c:when> <c:when test=”${cor == ‘Amarelo’}”> <c:out value=”a cor escolhida foi amarelo”/> </c:when> <c:otherwise> <c:out value=”não foi escolhida nenhuma cor”/> </ c:otherwise> </c:choose> </body> </html> Verifica se a variável cor é azul ou amarelo, caso seja, a cor é impressa na tela, caso contrário é impresso o texto não foi escolhida nenhuma cor. 274 Linguagens de Programação II.indb 274 7/12/2006 14:01:14 Linguagens de Programação II <c:forEach> - Executa o corpo da tag várias vezes. Essa tag possui comportamento semelhante ao comando for de Java. Ela possui seis atributos: items que representa o conjunto de dados que será percorrido, var que pode ser utilizado para definir a variável que receberá um item a cada iteração, begin, end e step que servem para delimitar os índices de início, fim e a freqüência da iteração. Essa tag possui ainda o atributo varStatus onde é possível acessar o status de cada iteração. Observe os exemplos a seguir: Utilização Resultado <c:forEach items=”${requestScope.candidatos}” var=”candidato”> <c:out value=”${candidato.nome}”/> </c:forEach> Irá recuperar a lista de candidatos que está no request e irá percorrê-la imprimindo o nome de cada candidato. <html> <body> <c:forEach items=”${lista}” var=”elemento”> <c:out value =’${elemento}’/> </c:forEach> </body> </html> Verifica se a variável lista existe em algum escopo (page, request, session ou application) e irá iterar sobre esse elemento até que todos os itens tenham sido acessados, para que o conteúdos de cada item possa ser impresso pela tag <c:out>. <c:forTokens> - Percorre uma String e interage com os tokens da mesma. Possui seis atributos: items que é preenchido com a String que será percorrida, delims onde são informados os tokens que serão buscados na String e como a tag <c:forEach> os atributos begin, end, step, var e varStatus. Veja os exemplos: Unidade 14 Linguagens de Programação II.indb 275 275 7/12/2006 14:01:15 Universidade do Sul de Santa Catarina Utilização Resultado <c:forTokens items=”um;dois;três/quatro” delims=”;/” var=”token”> <c:out value=”${token}”/> </c:forTokens> Será percorrida a String do atributo items e toda vez que for encontrado um dos tokens do atributo delims será impresso o conteúdo da variável token. <html> <body> <c:forTokens items=”um;dois;três/quatro” delims=”;/” var=”token”> <c:out value=”${token}”/><br/> </c:forTokens> </body> </html> Será impresso o seguinte conteúdo: um dois três quatro Lembrando que a quebra de linha ocorre devido ao elemento <br/> do HTML. <c:url> - Cria uma String com uma determinada URL. O atributo value deve ser preenchido com o valor da URL, o resultado é impresso na tela ou atribuído a uma variável definida pelo atributo var. Os exemplos são os seguintes: Utilização Resultado <c:url value=”/hello.jsp” var=”url”/> <c:out value=”${url}”/> Cria uma String contendo a URL para a página hello.jsp e imprime a URL. <html> <body> <c:url value=”/minhaPagina.jsp” var=”url”/> <c:out value=”${url}”/> </body> </html> Cria uma String contendo a URL para a página minhaPagina.jsp e imprime a URL na página. <c:param> - Permite passar parâmetros para uma URL. Pode ser utilizada dentro das tags <c:url>, <c:import> e <c:redirect>. O atributo name é preenchido com o nome do parâmetro e o atributo value com o respectivo valor. Veja os exemplos: 276 Linguagens de Programação II.indb 276 7/12/2006 14:01:15 Linguagens de Programação II Utilização Resultado <c:url value=”/hello.jsp” var=”url”> <c:param name=”id” value=”1”/> </c:url> Cria uma String contendo a URL para a página hello. jsp e adiciona o parâmetro id com o valor 1 para essa URL. Após isso, é criado um link para essa URL. <html> <body> <c:url value=”/hello.jsp” var=”url”> <c:param name=”id” value=”1”/> </c:url> <a href=’<c:out value=”${url}”/>’> link </a> </body> </html> Cria uma String contendo a URL para a página hello. jsp e adiciona o parâmetro id com o valor 1 para essa URL. Após isso, é criado um lin para essa URL. <c:import> - Permite importar o conteúdo de uma URL para dentro da página. Possui um atributo chamado url onde é preenchido o valor da URL de onde será recuperado o conteúdo. Acompanhe os exemplos: Utilização Resultado <c:import url=”http://www.google.com”/> Adiciona no ponto onde foi colocada a tag o conteúdo do site indicado no atributo URL. <html> <body> <c:import url=”http://www.terra.com.br”/> </body> </html> Dentro do body da página é importado o conteúdo da página do Terra. <c:redirect> - Redireciona o cliente de uma aplicação web para uma outra URL. Possui na tag <c:import> um atributo url onde deve ser especificado a URL para onde será feito o redirecionamento. Veja os exemplos: Unidade 14 Linguagens de Programação II.indb 277 277 7/12/2006 14:01:15 Universidade do Sul de Santa Catarina Utilização Resultado <c:redirect url=”http://www.google.com”/> Redireciona automaticamente para o endereço informado no atributo url. <html> <body> <c:redirect url=”http://www.google.com”/> </body> </html> Quando for processada a tag <c:redirect> o usuário será automaticamente redirecionado para o site do google. Vamos agora reescrever o último exemplo do capítulo anterior para utilizar JSTL: 1) Crie a seguinte estrutura de diretórios para a aplicação: sistemaExibeJSTL |-src |-paginas |-WEB-INF |-classes |-lib 2) Dentro do diretório páginas crie os seguintes arquivos: cabecalho.jsp <h1>Aplicação JSP</h1> Esta é uma demonstração da utilização dos vários recursos que JSP e biblioteca JSTL possuem<br/> 278 Linguagens de Programação II.indb 278 7/12/2006 14:01:15 Linguagens de Programação II conteudo.jsp <jsp:useBean id=”data” class=”java.util.Date”/> <html> <head> <title>Java Server Pages</title> </head> <body> <%@ include file=”cabecalho.jsp” %> <form action=”recuperaInformacoes.jsp” method=”post”> Nome: <input type=”text” name=”nome”/><br/> Data de Nascimento: <input type=”text” name=”dtaNascimento”/> <input type=”submit” value=”Enviar”/> </form> <%@ include file=”rodape.jsp” %> </body> </html> recuperaInformacoes.jsp <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core” %> <html> <head> <title>Java Server Pages</title> </head> <body> <%@ include file=”cabecalho.jsp” %> Você informou os seguintes dados: <br/> Nome : <c:out value=”${param.nome}/> <br/> Data de Nascimento: <c:out value=”${param.dtaNascimento}/><br/> <%@ include file=”rodape.jsp” %> </body> </html> rodape.jsp <h1>Hoje é <c:out value=”${data}”/></h1> 3) Crie, dentro do diretório WEB-INF, o arquivo web.xml com o seguinte conteúdo: <?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> <web-app> </web-app> Unidade 14 Linguagens de Programação II.indb 279 279 7/12/2006 14:01:16 Universidade do Sul de Santa Catarina 4) Copie para o diretório lib os arquivos: jstl.jar e standard.jar, localizados no pacote de distribuição do JSTL. 5) Copie o diretório sistemaExibe para o diretório $catalina_home/webapps. 6) Reinicie o Tomcat, abra o browser e digite http:// localhost:8080/sistemaExibe/paginas/conteudo.jsp. Você verá algo semelhante à figura a seguir: FIGURA 14.1 - PÁGINA PRINCIPAL Após preencher os dados e clicar no botão enviar, você verá algo semelhante à tela a seguir: FIGURA 14.2 - TELA DE RESULTADO Apesar do exemplo ser pequeno, note que agora extraímos o código Java de dentro dos JSPs. Dessa forma, a manutenção em páginas JSPs ficará muito mais fácil e, além do mais, a sintaxe utilizada nas páginas é a mesma utilizada em HTML, ou seja, uma pessoa responsável pelo design conseguirá manutenir essa 280 Linguagens de Programação II.indb 280 7/12/2006 14:01:16 Linguagens de Programação II página muito mais fácil do que se estivesse escrito uma porção de código Java dentro da página JSP. Na próxima unidade você estudará uma aplicação completa, utilizando tudo que já foi visto até aqui e indo além, pois será adicionado a nossa aplicação um banco de dados. Síntese Nesta unidade você pôde ver que a utilização da biblioteca JSTL simplifica bastante o desenvolvimento de páginas JSP, pois retira das páginas todo o código Java que geralmente é utilizado, quando as aplicações são desenvolvidas utilizando apenas JSP. Da mesma forma a utilização de JSTL torna o processo de manutenção dessas páginas bem menos custoso. Aliado a esses pontos a biblioteca JSTL estabelece uma sintaxe comum entre os desenvolvedores e designers, pois o resultado serão páginas seguindo o padrão HTML. Atividades de auto-avaliação Leia com atenção os enunciados seguintes e resolva as atividades programadas para a sua auto-avaliação. 1) Quais tags são utilizadas para fazer o controle de fluxo em páginas JSP? 2) Quais tags são responsáveis por fazer um laço de repeticação em páginas JSP? 3) Qual a sintaxe para utilizar linguagem de expressão nas tags JSTL? Unidade 14 Linguagens de Programação II.indb 281 281 7/12/2006 14:01:16 Universidade do Sul de Santa Catarina Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: GEARY, David. Core JSTL: mastering the JSP Standard Tag Library. [S. l.]: Prentice Hall, 2002. BAYERN, Shawn. JSTL in action. [S. l.]: Manning, 2003. http://java.sun.com/products/jsp/jstl/ (Site da especificação JSTL) http://jakarta.apache.org/taglibs/ (Site da implementação de referência da especificação JSTL) 282 Linguagens de Programação II.indb 282 7/12/2006 14:01:16 UNIDADE 15 Aplicação Web Objetivos de aprendizagem Desenvolver uma aplicação web Java. Utilizar as tecnologias de Servlets, JSP e JSTL. Utilizar como ambiente de execução o Apache Tomcat. Seções de estudo Seção 1 Especificação Seção 2 Implementação Linguagens de Programação II.indb 283 7/12/2006 14:01:16 Universidade do Sul de Santa Catarina Para início de conversa Até agora, você estudou as tecnologias Java para web e como elas funcionam. Nessa unidade construiremos uma aplicação que utilizará tudo o que vimos até agora. Então, vamos a especificação da aplicação. Todo o código fonte da aplicação está disponível na midiateca. Seção 1 - Especificação O mesmo projeto desenvolvido no módulo anterior será utilizado nesse momento. Porém, migraremos esse projeto para web. Ou seja, desenvolveremos Servlets para receberem os dados enviados pelos usuários, assim como também desenvolveremos páginas JSP com JSTL para exibir ao usuário as informações. Mas, o modelo de banco de dados estabelecido no módulo anterior será agora utilizado conforme a figura 15.1 a seguir: FIGURA 15.1 - MODELO ENTIDADE RELACIONAMENTO DO PROJETO 284 Linguagens de Programação II.indb 284 7/12/2006 14:01:16 Linguagens de Programação II O Modelo de classes a ser utilizado na aplicação é apresentado na figura 15.2. Na aplicação criamos duas classes DAO, seguindo o padrão Data Access Object. Esse padrão não será explicado detalhadamente agora. O que você precisa saber no momento é que esse padrão isola as classes de negócio das classes que vão executar comandos SQL em alguma base de dados. Dessa forma, nas classes ParticipanteDAO e ProjetoDAO conterão métodos para serem utilizados no banco de dados: inserir, apagar, atualizar, recuperar. Criamos também dois servlets que serão responsáveis por recuperar as informações fornecidas pelos usuários e preencher os objetos Participante e Projeto. Participante Servlet Participante Projeto ParticipanteDAO ProjetoDAO Projeto Servlet FIGURA 15.2 -MODELO DE CLASSE DA APLICAÇÃO Antes de começar a análise da implementação das nossas classes e páginas, veja como está organizado o nosso projeto. O projeto terá a seguinte estrutura de diretórios: Unidade 15 Linguagens de Programação II.indb 285 285 7/12/2006 14:01:17 Universidade do Sul de Santa Catarina aplicacaoWeb | src | - código fonte da aplicação. | WEB-INF |- classes |- classes compiladas |- lib | - bibliotecas que serão utilizadas pela aplicação (driver JDBC, e jars do JSTL) | - web.xml | - páginas JSP. Após a implementação da aplicação pode-se fazer a instalação da mesma no Servlet Container, apenas tomando cuidado de antes disso retirar o diretório src da aplicação, pois, de outra forma, quem acessar a aplicação pode ter acesso ao código fonte da mesma. Seção 2 - Implementação O código fonte possui o script SQL, necessário para a criação da base de dados. Esse script deve ser executado antes de se executar a aplicação, pois caso contrário, não funcionará. O banco de dados utilizado foi o MySQL 5.0.24. Lembre-se, ainda, que foi utilizada a versão do Java 5. Acompanhe o código do servlet ProjetoServlet: 286 Linguagens de Programação II.indb 286 7/12/2006 14:01:17 Linguagens de Programação II 1 public class ProjetoServlet extends HttpServlet { 2 3 4 5 6 7 8 private ProjetoDAO dao = new ProjetoDAOMySQL(); private ParticipanteDAO daoParticipante = new ParticipanteDAOMySQL(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String acao = request.getParameter(“acao”); 9 if (acao.equals(“salva”)) salvaProjeto(request,response); else if (acao.equals(“apaga”)) apagaProjeto(request,response); else if (acao.equals(“lista”)) listaProjetos(request,response); else editaProjeto(request,response); 10 11 12 13 } 14 protected void salvaProjeto(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ try{ Projeto projeto = preencheProjeto(request); dao.save(projeto); listaProjetos(request,response); }catch(ParseException e){ e.printStackTrace(); } } 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 protected void apagaProjeto(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ dao.delete(Integer.parseInt(request.getParameter(“idProjeto”))); listaProjetos(request,response); } protected void editaProjeto(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ Projeto projeto = null; try { projeto = dao.retrieveByPk(Integer.parseInt(request.getParameter (“idProjeto”))); Unidade 15 Linguagens de Programação II.indb 287 287 7/12/2006 14:01:17 Universidade do Sul de Santa Catarina 31 32 33 34 35 36 37 38 39 } catch (NumberFormatException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } request.setAttribute(“projeto”, projeto); request.setAttribute(“participantes”, daoParticipante.retrieveAll()); request.getRequestDispatcher(“/projeto.jsp”).forward(request,response); } 40 41 42 protected void listaProjetos(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ request.setAttribute(“projetos”, dao.retrieveAll()); request.getRequestDispatcher(“/projetos.jsp”).forward(request,response); 43 } 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 private Projeto preencheProjeto(HttpServletRequest request) throws ParseException{ String id = request.getParameter(“idProjeto”); String descProjeto = request.getParameter(“descProjeto”); String dataInicio = request.getParameter(“dataInicio”); String dataFim = request.getParameter(“dataFim”); int percConcluido = Integer.parseInt(request.getParameter(“percConcluido”)); String situacao = request.getParameter(“situacao”); String[] participantes = request.getParameterValues(“participantes”); Projeto projeto = new Projeto(); projeto.addParticipante(daoParticipante.retrieveByPk(Integer.parseInt(participantes[0]))); projeto.setIdProjeto(Integer.parseInt(id)); projeto.setDescricao(descProjeto); projeto.setDataInicio(dataInicio); projeto.setDataFim(dataFim); projeto.setPercentualConcluido(percConcluido); projeto.setSituacao(situacao); return projeto; } Veja a análise do código. Linha 1 - É feita a declaração de que esta classe é um servlet, pois herda de HttpServlet. Linha 2 e 3 - Repare também que o serlvet possui dois atributos para as classes DAO (ParticipanteDAO e ProjetoDAO). Como especificado no diagrama de classes, você verá que essas classes serão chamadas apenas quando se quer realizar alguma operação na base de dados, isolando os servlets das classes que conectam na base de dados. 288 Linguagens de Programação II.indb 288 7/12/2006 14:01:17 Linguagens de Programação II Linha 4 - Um ponto interessante a ser analisado nesse código fonte é como foi reescrito o método doGet, você pode notar que na implementação dele é feita uma chamada ao método doPost, ou seja, foi implementada a lógica uma única vez no método doPost e está sendo reutilizada no método doGet. Essa abordagem foi feita para que caso alguém faça uma requisição utilizando o método GET, o servlet não lançe uma exceção e execute as suas funções normalmente. Linha 7 - No método doPost é recuperado um parâmetro chamado acao. Esse parâmetro contém justamente que ação deve ser feita no momento. Baseado nisso, o servlet delega a tarefa a um determinado método. No servlet ProjetoServlet foram criados métodos relacionados as operações que poderiam ser feitas em um determinado projeto, ou seja, as operações de listar projetos (listaProjeto), apagar projetos (apagaProjeto) e salvar modificações em projetos (salvaProjeto). Linha 14 - No método salvaProjeto é criado um objeto Projeto por meio do método preencheProjeto. Esse método é responsável por capturar todos os parâmetros informados na página a respeito do projeto, criar um novo projeto e devolvêlo. Após o recebimento desse novo objeto Projeto, o método salvaProjeto chama o método save da classe ProjetoDAO. Essa classe é responsável por efetuar as operações do projeto no banco de dados. Por fim, é chamado o método listaProjetos, pois é justamente para onde o usuário será direcionado após ter salvo informações de um projeto. Repare também que é feito um tratamento de exceção, pois no método preecheProjeto é possível ser lançada uma exceção. Linha 23 - No método apagaProjeto o comportamento é semelhante ao do salvaProjeto. Porém, ele irá recuperar o identificador do projeto que virá na requisição e com base nisso irá procurar o projeto na base de dados por meio do método retrieveByPK da classe ProjetoDAO. Depois de ter apagado o projeto, o método listaProjetos é chamado, que é para onde o usuário será direcionado. Unidade 15 Linguagens de Programação II.indb 289 289 7/12/2006 14:01:17 Universidade do Sul de Santa Catarina Linha 27 - No método editaProjeto a grande novidade é a utilização de dois métodos o setAttribute da classe HttpServletRequest. Esse método permite que coloquemos dentro da requisição objetos. Dessa forma, pode-se acessar esse objetos nas nossas páginas JSP. Você verá como acessar esse objetos colocados na requisição, mais a frente. O outro método novo que você verá é o forward da classe RequestDispatcher. Essa classe RequestDispatcher que é recuperada a partir de uma requisição (request. getRequestDispatcher) permite que os servlets encaminhem a requisição para algum recurso, geralmente uma página JSP. Dessa forma, é possível utilizar servlets em conjunto com JSPs. Nas linhas seguintes estão localizados os métodos listaProjetos e preecheProjetos. Como eles já foram comentados acima, não serão abordados novamente. A seguir é apresentado o servlet ParticipanteServlet que segue a mesma filosofia do ProjetoServlet: 1 public class ParticipanteServlet extends HttpServlet { 2 private ParticipanteDAO dao = new ParticipanteDAOMySQL(); 3 private ProjetoDAO daoProjeto = new ProjetoDAOMySQL(); 4 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 5 doPost(request, response); 6 } 7 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 8 String acao = request.getParameter(“acao”); 9 10 11 12 13 14 15 16 17 } if (acao.equals(“salva”)) salvaParticipante(request,response); else if (acao.equals(“apaga”)) apagaParticipante(request,response); else if (acao.equals(“lista”)) listaParticipante(request, response); else editaParticipante(request,response); 18 protected void salvaParticipante(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 19 try{ 290 Linguagens de Programação II.indb 290 7/12/2006 14:01:18 Linguagens de Programação II 20 21 22 23 24 25 26 } 27 Participante participante = preencheParticipante(request); dao.save(participante); listaParticipante(request,response); }catch(ParseException e){ e.printStackTrace(); } 28 protected void apagaParticipante(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 29 dao.delete(Integer.parseInt(request.getParameter(“idParticipante”))); 30 listaParticipante(request, response); 31 } 32 protected void editaParticipante(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 33 Participante participante = dao.retrieveByPk(Integer.parseInt(request.getParameter(“id Participante”))); 34 request.setAttribute(“participante”, participante); 35 request.setAttribute(“projetos”, daoProjeto.retrieveAll()); 36 request.getRequestDispatcher(“/participante.jsp”).forward(request,response); 37 } 38 protected void listaParticipante(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 39 request.setAttribute(“participantes”, dao.retrieveAll()); 40 request.getRequestDispatcher(“/participantes.jsp”).forward(request,response); 41 } 42 private Participante preencheParticipante(HttpServletRequest request) throws ParseException{ 43 String id = request.getParameter(“idParticipante”); 44 String nome = request.getParameter(“nome”); 45 String cargo = request.getParameter(“cargo”); 46 String[] projetos = request.getParameterValues(“projetos”); 47 Participante participante = new Participante(); int posição = Integer.parseInt(projetos[0]); 48 participante.addProjeto(daoProjeto.retrieveByPk(posicao)); 49 participante.setIdParticipante(Integer.parseInt(id)); 50 participante.setNome(nome); 51 participante.setCargo(cargo); 52 return participante; 53 } 54 } Unidade 15 Linguagens de Programação II.indb 291 291 7/12/2006 14:01:18 Universidade do Sul de Santa Catarina Verifique que o servlet ParticipanteServlet é semelhante ao servlet Projeto, porém ele trata uma unidade de informação diferente, no caso Participante. Veja, agora, como foi estruturada a parte que irá persistir as informações no banco de dados. Como comentado anteriormente, foi informado a utilização do padrão DAO para separar a lógica de negócio da lógica de persistência. A seguir são apresentadas as interfaces ParticipanteDAO e ProjetoDAO: public interface ParticipanteDAO { public boolean save(Participante participante); public boolean delete(int primaryKey); public Participante retrieveByPk(int primaryKey); public Participante retrieveByNome(String nome); public List retrieveAll(); } public interface ProjetoDAO { public boolean save(Projeto Projeto) throws ParseException; public boolean delete(int primaryKey); public Projeto retrieveByPk(int primaryKey) throws ParseException; public Projeto retrieveByDescricao(String nome); public List retrieveAll(); } Verifique que nas duas interfaces foram especificados apenas os métodos que poderão ser utilizados. Mas por que isso? Dessa forma, você poderá ter várias implementações que acessarão diferentes bancos de dados, porém respeitando os métodos estabelecidos pela interface. 292 Linguagens de Programação II.indb 292 7/12/2006 14:01:18 Linguagens de Programação II Assim, é possível diminuir o nível de amarração da aplicação a um determinado banco de dados, ou seja, reduzir o acoplamento. Acompanhe, a seguir, as implementações dessas interfaces, com as classes ParticipanteDAOMySQL e ProjetoDAOMySQL: 1 public class ParticipanteDAOMySQL implements ParticipanteDAO { 2 public boolean delete(int primaryKey) { 3 boolean resultado = false; 4 Connection conn = null; 5 PreparedStatement pstmt = null; 6 try { 7 Class.forName(“com.mysql.jdbc.Driver”); 8 String URL = “jdbc:mysql://localhost:3306/livro”; 9 conn = DriverManager.getConnection(URL,”root”,”admin”); 10 String sql = “delete from participantes where idParticipantes = ?”; 11 pstmt = conn.prepareStatement(sql); 12 pstmt.setInt(1,primaryKey); 13 pstmt.executeUpdate(); 14 resultado = true; 15 } catch (ClassNotFoundException e) { 16 e.printStackTrace(); 17 } catch (SQLException e) { 18 e.printStackTrace(); 19 }finally{ 20 if (pstmt != null){ 21 try{ 22 pstmt.close(); 23 }catch(SQLException e){ 24 e.printStackTrace(); 25 } 26 } 27 if(conn != null) { 28 try{ 29 conn.close(); 30 }catch(SQLException e){ 31 e.printStackTrace(); 32 } 33 } 34 } 35 return resultado; 36 } 37 public boolean save(Participante participante) { 38 boolean resultado = false; 39 Connection conn = null; 40 PreparedStatement pstmt = null; 41 try { 42 Class.forName(“com.mysql.jdbc.Driver”); 43 String URL = “jdbc:mysql://localhost:3306/livro”; 44 conn = DriverManager.getConnection(URL,”root”,”admin”); 45 String sql = null; 46 if (participante.getIdParticipante() != 0) 47 sql = “update participantes set vNome = ?, vCargo = ? where idParticipantes = ?”; 48 else Unidade 15 Linguagens de Programação II.indb 293 293 7/12/2006 14:01:18 Universidade do Sul de Santa Catarina 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 } sql = “insert into participantes (vNome, vCargo) values (?,?)”; pstmt = conn.prepareStatement(sql); pstmt.setString(1,participante.getNome()); pstmt.setString(2, participante.getCargo()); if (participante.getIdParticipante() != 0){ pstmt.setInt(3,participante.getIdParticipante()); saveProjetos(participante); } pstmt.executeUpdate(); resultado = true; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return resultado; 81 public boolean saveProjetos(Participante participante) { 82 boolean resultado = false; 83 Connection conn = null; 84 PreparedStatement pstmt = null; 85 try { 86 Class.forName(“com.mysql.jdbc.Driver”); 87 String URL = “jdbc:mysql://localhost:3306/livro”; 88 conn = DriverManager.getConnection(URL,”root”,”admin”); 89 String sql = “insert into controles (Projetos_idProjetos, Participantes_idParticipantes) values (?,?)”; 90 pstmt = conn.prepareStatement(sql); 91 pstmt.setInt(1, participante.getProjetos().get(0).getIdProjeto()); 92 pstmt.setInt(2,participante.getIdParticipante()); 93 pstmt.executeUpdate(); 94 resultado = true; 95 } catch (ClassNotFoundException e) { 96 e.printStackTrace(); 97 } catch (SQLException e) { 98 e.printStackTrace(); 99 }finally{ 100 if (pstmt != null){ 294 Linguagens de Programação II.indb 294 7/12/2006 14:01:18 Linguagens de Programação II 101 try{ 102 pstmt.close(); 103 }catch(SQLException e){ 104 e.printStackTrace(); 105 } 106 } 107 if(conn != null) { 108 try{ 109 conn.close(); 110 }catch(SQLException e){ 111 e.printStackTrace(); 112 } 113 } 114 } 115 return resultado; 116 } 117 public Participante retrieveByPk(int primaryKey) { 118 Participante participante = null; 119 Connection conn = null; 120 PreparedStatement pstmt = null; 121 ResultSet rs = null; 122 try { 123 Class.forName(“com.mysql.jdbc.Driver”); 124 String URL = “jdbc:mysql://localhost:3306/livro”; 125 conn = DriverManager.getConnection(URL,”root”,”admin”); 126 String sql = “select * from participantes where idParticipantes = ?”; 127 pstmt = conn.prepareStatement(sql); 128 pstmt.setInt(1,primaryKey); 129 rs = pstmt.executeQuery(); 130 while (rs.next()) { 131 participante = new Participante(); 132 participante.setIdParticipante(rs.getInt(“idParticipantes”)); 133 participante.setNome(rs.getString(“vNome”)); 134 participante.setCargo(rs.getString(“vCargo”)); 135 } 136 } catch (ClassNotFoundException e) { 137 e.printStackTrace(); 138 } catch (SQLException e) { 139 e.printStackTrace(); 140 }finally{ 141 if (rs != null){ 142 try{ 143 rs.close(); 144 }catch(SQLException e){ 145 e.printStackTrace(); 146 } 147 } 148 if (pstmt != null){ 149 try{ 150 pstmt.close(); 151 }catch(SQLException e){ 152 e.printStackTrace(); 153 } Unidade 15 Linguagens de Programação II.indb 295 295 7/12/2006 14:01:19 Universidade do Sul de Santa Catarina 154 155 156 157 158 159 160 161 162 163 164 } if(conn != null) { try{ } 165 166 167 168 169 170 171 172 173 174 175 176 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 public Participante retrieveByNome(String nome) { Participante participante = null; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “select * from participantes where vNome = ?”; pstmt = conn.prepareStatement(sql); pstmt.setString(1,nome); rs = pstmt.executeQuery(); while (rs.next()) { participante = new Participante(); participante.setIdParticipante(rs.getInt(“idParticipantes”)); participante.setNome(rs.getString(“vNome”)); participante.setCargo(rs.getString(“vCargo”)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return participante; 296 Linguagens de Programação II.indb 296 7/12/2006 14:01:19 Linguagens de Programação II 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 } } } } return participante; } public List retrieveAll() { Participante participante = null; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; ArrayList<Participante> lista = new ArrayList<Participante>(); try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “select * from participantes”; pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()) { participante = new Participante(); participante.setIdParticipante(rs.getInt(“idParticipantes”)); participante.setNome(rs.getString(“vNome”)); participante.setCargo(rs.getString(“vCargo”)); lista.add(participante); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return lista; } Unidade 15 Linguagens de Programação II.indb 297 297 7/12/2006 14:01:19 Universidade do Sul de Santa Catarina Linha 1 – Veja, na primeira linha, que a nossa classe se chama ParticipanteDAOMySQL e ela implementa a interface ParticipanteDAO. Por que isso? Imagine que você tem mais de um banco de dados, e assim, você terá algumas sintaxes proprietárias de cada banco, o que tornará inviável você colocar toda a lógica de acesso aos dados em uma única classe. Dessa forma, estabeleceu-se uma interface para especificar os métodos que todos que a implementarem devem possuir e, a partir daí, pode ser implementada uma classe para cada banco utilizado. No nosso caso foi utilizado o MySQL. Linha 2 a 35 - É implementado o método delete, que irá remover da base de dados um determinado participante, baseado no identificador desse participante. A partir daí, o processo normal de conexão com banco de dados e a execução de comando SQL é feita. Linha 37 a 80 - Nesse trecho é implementado o método saveParticipante, em que as informações do participante serão salvas. Perceba que na linha 46 é feita uma verificação justamente para saber se o comando a ser executado no MySQL será uma atualização ou uma inserção do participante na base de dados. Linha 81 a 116 - Os projetos vinculados a um participante são salvos na base de dados nesse momento. Linha 117 a 164 - A recuperação de um participante da base de dados é feita nesse momento. Repare que nesse método a recuperação é feita com base no identificador do participante. Linha 165 a 213 - Nesse trecho de código, é feita a mesma lógica do método anterior. Porém, agora a busca é feita pelo nome do participante e não pelo identificador do participante. Linha 214 a 262 - Neste método é feita uma busca para retornar todos os participantes cadastrados no sistema. 298 Linguagens de Programação II.indb 298 7/12/2006 14:01:20 Linguagens de Programação II A seguir é apresentado a listagem do código relativo ao ProjetoDAOMySQL: 001 package br.unisul.persistence.mysql; 002 003 import java.sql.Connection; 004 import java.sql.DriverManager; 005 import java.sql.PreparedStatement; 006 import java.sql.ResultSet; 007 import java.sql.SQLException; 008 import java.text.ParseException; 009 import java.text.SimpleDateFormat; 010 import java.util.ArrayList; 011 import java.util.Date; 012 import java.util.List; 013 import br.unisul.model.Projeto; 014 import br.unisul.persistence.ProjetoDAO; 015 016 public class ProjetoDAOMySQL implements ProjetoDAO { 017 018 public boolean save(Projeto projeto) throws ParseException { 019 boolean resultado = false; 020 Connection conn = null; 021 PreparedStatement pstmt = null; 022 try { 023 Class.forName(“com.mysql.jdbc.Driver”); 024 String URL = “jdbc:mysql://localhost:3306/livro”; 025 conn = DriverManager.getConnection(URL,”root”,”admin”); 026 String sql = null; 027 if (projeto.getIdProjeto() != 0) 028 sql = “update projetos set vDescricao = ?, dDataInicio = ?, dDataFinal = ?, nPercConcluido = ?, vSituacao = ? where idProjetos = ?”; 029 else 030 sql = “insert into projetos (vDescricao, dDataInicio, dDataFinal, nPercConcluido, vSituacao) values (?,?,?,?,?)”; 031 SimpleDateFormat formatador = new SimpleDateFormat(“dd/MM/yyyy”); 032 pstmt = conn.prepareStatement(sql); 033 pstmt.setString(1,projeto.getDescricao()); 034 pstmt.setDate(2,new java.sql.Date(formatador.parse(projeto.getDataInicio()).getTime())); 035 pstmt.setDate(3,new java.sql.Date(formatador.parse(projeto.getDataFim()).getTime())); 036 pstmt.setInt(4, projeto.getPercentualConcluido()); 037 pstmt.setString(5, projeto.getSituacao()); 038 if (projeto.getIdProjeto() != 0){ 039 pstmt.setInt(6,projeto.getIdProjeto()); 040 saveParticipantes(projeto); 041 } 042 pstmt.executeUpdate(); 043 resultado = true; 044 } catch (ClassNotFoundException e) { 045 e.printStackTrace(); 046 } catch (SQLException e) { 047 e.printStackTrace(); 048 }finally{ 049 if (pstmt != null){ 050 try{ Unidade 15 Linguagens de Programação II.indb 299 299 7/12/2006 14:01:20 Universidade do Sul de Santa Catarina 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return resultado; } public boolean saveParticipantes(Projeto projeto) { boolean resultado = false; Connection conn = null; PreparedStatement pstmt = null; try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “insert into controles (Projetos_idProjetos, Participantes_idParticipantes) values (?,?)”; pstmt = conn.prepareStatement(sql); pstmt.setInt(1,projeto.getIdProjeto()); pstmt.setInt(2, projeto.getParticipantes().get(0).getIdParticipante()); pstmt.executeUpdate(); resultado = true; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } 300 Linguagens de Programação II.indb 300 7/12/2006 14:01:20 Linguagens de Programação II 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 return resultado; } public boolean delete(int primaryKey) { boolean resultado = false; Connection conn = null; PreparedStatement pstmt = null; try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “delete from projetos where idProjetos = ?”; pstmt = conn.prepareStatement(sql); pstmt.setInt(1,primaryKey); pstmt.executeUpdate(); resultado = true; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return resultado; } public Projeto retrieveByPk(int primaryKey) throws ParseException { Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; Projeto projeto = null; try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “select idProjetos, vDescricao, “ + “DATE_FORMAT(dDataInicio, ‘%d/%m/%y’) as dDataInicio, “+ “DATE_FORMAT(dDataFinal, ‘%d/%m/%y’) as dDataFinal, “+ “nPercConcluido, vSituacao from projetos where idProjetos = ?”; Unidade 15 Linguagens de Programação II.indb 301 301 7/12/2006 14:01:20 Universidade do Sul de Santa Catarina 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 pstmt = conn.prepareStatement(sql); pstmt.setInt(1,primaryKey); rs = pstmt.executeQuery(); while (rs.next()) { projeto = new Projeto(); projeto.setIdProjeto(rs.getInt(“idProjetos”)); projeto.setDescricao(rs.getString(“vDescricao”)); projeto.setDataInicio(rs.getString(“dDataInicio”)); projeto.setDataFim(rs.getString(“dDataFinal”)); projeto.setPercentualConcluido(rs.getInt(“nPercConcluido”)); projeto.setSituacao(rs.getString(“vSituacao”)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return projeto; } public Projeto retrieveByDescricao(String nome) { Projeto projeto = null; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “select idProjetos, vDescricao, “+ 302 Linguagens de Programação II.indb 302 7/12/2006 14:01:21 Linguagens de Programação II “DATE_FORMAT(dDataInicio, ‘%d/%m/%y’) as dDataInicio, “+ “DATE_FORMAT(dDataFinal, ‘%d/%m/%y’) as dDataFinal, “+ “nPercConcluido, vSituacao from projetos where vDescricao = ?”; pstmt = conn.prepareStatement(sql); pstmt.setString(1,nome); rs = pstmt.executeQuery(); while (rs.next()) { projeto = new Projeto(); projeto.setIdProjeto(rs.getInt(“idProjetos”)); projeto.setDescricao(rs.getString(“vDescricao”)); projeto.setDataInicio(rs.getString(“dDataInicio”)); projeto.setDataFim(rs.getString(“dDataFinal”)); projeto.setPercentualConcluido(rs.getInt(“nPercConcluido”)); projeto.setSituacao(rs.getString(“vSituacao”)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ if (rs != null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if (pstmt != null){ try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn != null) { try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } return projeto; 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 } 243 244 public List retrieveAll() { 245 Projeto projeto = null; 246 ArrayList<Projeto> lista = new ArrayList<Projeto>(); 247 Connection conn = null; 248 PreparedStatement pstmt = null; 249 ResultSet rs = null; 250 try { Unidade 15 Linguagens de Programação II.indb 303 303 7/12/2006 14:01:21 Universidade do Sul de Santa Catarina 251 252 253 254 Class.forName(“com.mysql.jdbc.Driver”); String URL = “jdbc:mysql://localhost:3306/livro”; conn = DriverManager.getConnection(URL,”root”,”admin”); String sql = “select idProjetos, vDescricao, “+ “DATE_FORMAT(dDataInicio, ‘%d/%m/%y’) as dDataInicio, “+ “DATE_FORMAT(dDataFinal, ‘%d/%m/%y’) as dDataFinal, “+ “nPercConcluido, vSituacao from projetos”; 255 pstmt = conn.prepareStatement(sql); 256 rs = pstmt.executeQuery(); 257 while (rs.next()) { 258 projeto = new Projeto(); 259 projeto.setIdProjeto(rs.getInt(“idProjetos”)); 260 projeto.setDescricao(rs.getString(“vDescricao”)); 261 projeto.setDataInicio(rs.getString(“dDataInicio”)); 262 projeto.setDataFim(rs.getString(“dDataFinal”)); 263 projeto.setPercentualConcluido(rs.getInt(“nPercConcluido”)); 264 projeto.setSituacao(rs.getString(“vSituacao”)); 265 lista.add(projeto); 266 } 267 } catch (ClassNotFoundException e) { 268 e.printStackTrace(); 269 } catch (SQLException e) { 270 e.printStackTrace(); 271 }finally{ 272 if (rs != null){ 273 try{ 274 rs.close(); 275 }catch(SQLException e){ 276 e.printStackTrace(); 277 } 278 } 279 if (pstmt != null){ 280 try{ 281 pstmt.close(); 282 }catch(SQLException e){ 283 e.printStackTrace(); 284 } 285 } 286 if(conn != null) { 287 try{ 288 conn.close(); 289 }catch(SQLException e){ 290 e.printStackTrace(); 291 } 292 } 293 } 294 return lista; 295 } 296 297 } Perceba que o código é muito semelhante ao ParticipanteDAOMysQL. Porém, agora é tratada a unidade de informação Projeto. 304 Linguagens de Programação II.indb 304 7/12/2006 14:01:21 Linguagens de Programação II A seguir veremos a página JSP de cadastro de participante no projeto: 1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core”%> <html> <body> <h1>Novo Participante</h1><br/> <form action=”participanteServlet” method=”POST”> <input type=”hidden” name=”acao” value=”salva”/> <input type=”hidden” name=”idParticipante” value=’<c:out value=”${param.idParticipante}”/>’/> Nome: <input type=”text” name=”nome” value=’<c:out value=”${participante.nome}”/>’/> <br/> Cargo: <input type=”text” name=”cargo” size=”8” value=’<c:out value=”${participante.cargo}”/>’/> <br/> <c:if test=”${participante.idParticipante != null}”> Projetos <select name=”projetos”> <c:forEach items=”${projetos}” var=”projeto”> <option value=’<c:out value=”${projeto.idProjeto}”/>’><c:out value=”${projeto. descricao}”/></option> 14 </c:forEach> 15 </select><br> 16 </c:if> 17 <p/>&nbsp; 18 <input type=”submit” value=”Salvar”> 19 </form> 20 </body> 21 </html> Linha 1 – foi feita a declaração para utilizar a biblioteca Core do JSTL. Linha 6 – foi criado um campo escondido para informar qual ação será executada no servlet ParticipanteServlet, no caso, a ação será salva. Linha 7 – foi recuperado o identificador do participante, pois esta página é utilizada tanto para cadastrar um novo participante quanto um editar um já existente. Caso se esteja editando, você precisa desse campo para poder atualizar o registro desse participante na base de dados. Perceba que estamos utilizando JSTL para recuperar o identificador do participante. Linhas 7, 8 e 9 - Verifique que estamos utilizando JSTL para preencher os 3 campos dos formulário apresentados nessas linhas. Porém, se quando forem analisadas as expressões da tag <c:out> for verificado que não possui valor nenhum, então é retornada uma String vazia. Dessa forma, os nossos campos não ficarão com caracteres estranhos ou mesmo com o texto “<c:out value=”${participante.nome}”/>”. Unidade 15 Linguagens de Programação II.indb 305 305 7/12/2006 14:01:21 Universidade do Sul de Santa Catarina Linha 10 - é utilizado JSTL novamente para fazer uma decisão se o combo de projetos deve aparecer na página nesse momento ou não. Caso esteja sendo editado o cadastro do participante é habilitado o combo com os projetos para serem selecionados. A seguir é apresentada a página de listagem dos participantes: 1 <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core”%> 2 <html> 3 <body> 4 <table> 5 <td><h1>Projetos cadastrados</h1></td> 6 <c:forEach items=”${participantes}” var=”participante” varStatus=”status”> 7 <tr> 8 <td>Participante#<c:out value=”${status.count}”/>: <c:out value=”${participante.nome}”/> | 9 <a href=’participanteServlet?acao=edita&idParticipante=<c:out value=”${participante. idParticipante}”/>’>Editar</a> | 10 <a href=’participanteServlet?acao=apaga&idParticipante=<c:out 11 value=”${participante.idParticipante}”/>’>Apagar</a> 12 </td> 13 </tr> 14 </c:forEach> 15 </table> 16 </body> 17 </html> Linha 1 - novamente é feita a declaração para utilização da biblioteca Core do JSTL. Linha 6 - é utilizada a tag <c:forEach> para se percorrer a lista de participantes para poder imprimi-los na página. Essa lista é aquele objeto que foi colocado no request por meio do método setAttribute quando estávamos analisando o código do ProjetoServlet. Linha 9 - é construído um link para acessar um determinado participante, para poder editá-lo ou apagá-lo. Note que a referência desse link é diretamente para o servlet e já passamos a ação que será executada com o identificador do participante. Por exemplo, <a href=’participanteServlet?acao=apaga&idP articipante=<c:out value=”${participante.idParticipante}”/ >’>Apagar</a> está informando que o link para poder apagar um participante será: participanteSerlvet com o parâmetro “acao” 306 Linguagens de Programação II.indb 306 7/12/2006 14:01:21 Linguagens de Programação II sendo apaga e que o idParticipante será o valor do resultado da execução da tag <c:out> As páginas relacionadas ao projeto seguem o mesmo princípio das páginas dos participantes e podem ser encontradas no arquivo que contém o código fonte. Como acontece com os participantes, o projeto também possui uma página de cadastro dos projetos e uma para listar os projetos existentes. O código das duas páginas é apresentado a seguir: projeto.jsp 1 2 3 4 5 6 7 8 <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core”%> <html> <body> <h1>Novo Projeto</h1><br/> <form action=”projetoServlet” method=”POST”> <input type=”hidden” name=”acao” value=”salva”/> <input type=”hidden” name=”idProjeto” value=’<c:out value=”${param.idProjeto}”/>’/> Descrição: <input type=”text” name=”descProjeto” value=’<c:out value=”${projeto. descricao}”/>’/> <br/> 9 Data de Início: <input type=”text” name=”dataInicio” size=”8” value=’<c:out value=”${projeto.dataInicio}”/>’/> 10 <br/> 11 Data de Fim: <input type=”text” name=”dataFim” size=”8” value=’<c:out value=”${projeto. dataFim}”/>’/> <br/> 12 Percentual Concluído: <input type=”text” name=”percConcluido” size=”3” value=’<c:out value=”${projeto.percentualConcluido}”/>’/> <br/> 13 Situação: <input type=”text” name=”situacao” value=’<c:out value=”${projeto. situacao}”/>’/> <br/> 14 <c:if test=”${projeto.idProjeto != null}”> 15 Participante <select name=”participantes”> 16 <c:forEach items=”${participantes}” var=”part”> 17 <option value=’<c:out value=”${part.idParticipante}”/>’><c:out value=”${part. nome}”/></option> 18 </c:forEach> 19 </select><br> 20 </c:if> 21 <p/>&nbsp; 22 <input type=”submit” value=”Salvar”> 23 </form> 24 </body> 25 </html> Unidade 15 Linguagens de Programação II.indb 307 307 7/12/2006 14:01:22 Universidade do Sul de Santa Catarina projetos.jsp 1 <%@ taglib prefix=”c” uri=”http://java.sun.com/jstl/core”%> 2 <html> 3 <body> 4 <table> 5 <td><h1>Projetos cadastrados</h1></td> 6 <c:forEach items=”${projetos}” var=”projeto” varStatus=”status”> 7 <tr> 8 <td>Projeto#<c:out value=”${status.count}”/>: <c:out value=”${projeto.descricao}”/> | 9 <a href=’projetoServlet?acao=edita&idProjeto=<c:out value=”${projeto.idProjeto}”/>’>Editar</a> | 10 <a href=’projetoServlet?acao=apaga&idProjeto=<c:out value=”${projeto.idProjeto}”/>’>Apagar</a> 11 </td> 12 </tr> 13 </c:forEach> 14 </table> 15 </body> 16 </html> A seguir veja o conteúdo do descritor da aplicação web.xml: 1 <?xml version=”1.0” encoding=”UTF-8”?> 2 <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”> 3 <web-app> 4 <servlet> 5 <servlet-name>projetoServlet</servlet-name> 6 <servlet-class>br.unisul.control.ProjetoServlet</servlet-class> 7 </servlet> 8 <servlet> 9 <servlet-name>participanteServlet</servlet-name> 10 <servlet-class>br.unisul.control.ParticipanteServlet</servlet-class> 11 </servlet> 12 <servlet-mapping> 13 <servlet-name>projetoServlet</servlet-name> 14 <url-pattern>/projetoServlet</url-pattern> 15 </servlet-mapping> 16 <servlet-mapping> 17 <servlet-name>participanteServlet</servlet-name> 18 <url-pattern>/participanteServlet</url-pattern> 19 </servlet-mapping> 20 </web-app> Acompanhe a análise do código. Linha 1 e 2 - cabeçalho padrão dos descritores de aplicação. Linha 5 e 6 - atribuído um identificador ao servlet ProjetoServlet. Dentro do nosso descritor ele será referenciado como projetoSerlvet. 308 Linguagens de Programação II.indb 308 7/12/2006 14:01:22 Linguagens de Programação II Linha 9 e 10 - o mesmo propósito da explicação anterior, porém agora o identificador é para um servlet direfente e o próprio identificar é diferente, no caso, participanteServlet. Linha 13 e 14 - vinculação do servlet projetoServlet ao padrão de url /projetoServlet, ou seja, toda vez que chegar uma requisição que no seu endereço contenha o conteúdo ../projetoServlet..., essa requisição será encaminhada ao servlet projetoServlet. Linha 17 e 18 - o mesmo princípio explicado anteiormente, porém para o servlet do participante. Lembre-se que para essa aplicação o processo de compilação dos Servlets deve ser o mesmo utilizado nos exemplos dos capítulos anteriores, ou seja: javac –classpath $catalina_home/common/lib/servlet-api.jar –d WEB-INF/classes src/ MeuPrimeiroServlet.java Atenção! Lembre-se de dois pontos: o comando deve estar numa linha apenas e substitua $catalina_home pelo diretório onde está localizado o Tomcat. Unidade 15 Linguagens de Programação II.indb 309 309 7/12/2006 14:01:22 Universidade do Sul de Santa Catarina Síntese Ao longo dessa unidade, você viu como unir o estudado até agora em uma aplicação web. Essa foi apenas a primeira parte, pois existe muitas tecnologias da Sun que dão suporte ao desenvolvimento de aplicações web. Procure, sempre que desenvolver aplicações web, utilizar tecnologias que auxiliem no desenvolvimento e principalmente facilitem a manutenção do sistema. Porém, você deve utilizar as tecnologias em conjunto com a orientação a objetos. Dessa forma, você conseguirá desenvolver aplicações possíveis de sofrerem manutenção, seja ela corretiva, adaptativa ou evolutiva. Atividades de auto-avaliação Leia com atenção os enunciados seguintes e resolva as atividades programadas para a sua auto-avaliação. 1) Como foi feito o mapeamento dos Servlets da aplicação de exemplo? 2) Qual o padrão de projeto que procura isolar o código relacionado a banco de dados em classes específicas? 310 Linguagens de Programação II.indb 310 7/12/2006 14:01:22 Linguagens de Programação II Saiba mais Você pode saber mais sobre o assunto estudado nesta unidade consultando as seguintes referências: GEARY, David. Core JSTL: mastering the JSP Standard Tag Library. [S. l.]: Prentice Hall, 2002. BAYERN, Shawn. JSTL in action. [S. l.]: Manning, 2003. HALL, Marty. Core Servlets and JavaServer Pages. [S. l.]: Prentice Hall, [200?]. HALL, Marty. More Servlets and JavaServer Pages. [S. l.]: Pearson Education, [200?]. FIELDS, Duane; KOLB, Mark; Web development with Java Server Pages. [S. l.]: Manning Publications, 2000. SIERRA, Kathy; BASHMAN, Brian; BATES, Bert. Head first Servlets and JSP. [S. l.]: O’Reilly, 2004. http://java.sun.com/products/jsp/jstl/ (Site da especificação JSTL) http://jakarta.apache.org/taglibs/ (Site da implementação de referência da especificação JSTL) http://servlets.com/ (Site com muito material sobre a tecnologia Java Servlets) http://tomcat.apache.org/ (Site oficial do projeto Apache Tomcat) http://java.sun.com/products/servlet/ (Site oficial da Sun sobre a tecnologia Java Servlets) http://www.jcp.org/aboutJava/communityprocess/final/jsr154/index. html (Site da especificação dos Java Servlets) http://www.w3.org/CGI/ (Site do consórcio W3C sobre a tecnologia CGI) http://www.w3.org/Protocols/ (Site do consórcio W3C sobre o protocolo http) Unidade 15 Linguagens de Programação II.indb 311 311 7/12/2006 14:01:22 Linguagens de Programação II.indb 312 7/12/2006 14:01:22 Para concluir o estudo Caro aluno! Concluímos mais uma etapa do curso. A disciplina de Linguagem de Programação II chegou ao fim. Nessa disciplina você aprendeu três tópicos muito importantes exigidos no desenvolvimento de sistemas mais profissionais. O desenvolvimento de interfaces gráficas é vital para a usabilidade de um sistema. Sistemas que manipulam dados em um banco de dados também. E o desenvolvimento de aplicações que rodem na web é, nos dias de hoje, um requisito primordial no desenvolvimento de sistemas. A intenção nesse livro foi destacar os itens mais importantes desses três tópicos. Procuramos dividir o livro de forma que os três tópicos tivessem o mesmo número de unidades visto que os três assuntos são importantes. Não se pretende esgotar o assunto referente a eles nesse livro. Uma prova disto é que você terá mais uma disciplina de programação que abordará com mais profundidade o tópico de desenvolvimento de aplicações para web. Foi um trabalho longo e de um nível técnico mais elevado, que exigiu de você o conhecimento de todas as disciplinas de programação cursadas até o momento. É importante destacar que a tendência é que o nível técnico das disciplinas de programação aumente com a aproximação do término do curso. Porém, acreditamos que se você está lendo essas páginas finais é muito provável que esse desafio tenha sido vencido. Esperamos que você tenha gostado da disciplina. Linguagens de Programação II.indb 313 7/12/2006 14:01:22 Linguagens de Programação II.indb 314 7/12/2006 14:01:23 Referências BAYERN, Shawn. JSTL in action. [S. l.]: Manning, 2003. DATE, C. J. Bancos de dados: fundamentos. Rio de Janeiro: Campus, 1985. DATE, C. J. Introdução ao sistema de banco de dados. 8 ed. Rio de Janeiro: Campus, 1990. DEITEL, H. M.; DEITEL, P. J. Java como programar. 6 ed. Porto Alegre: Person, 2005. FALKNER, Jason. JONES, Kevin. Servlets and Java Server Pages: the J2EE technology web tier. [S. l.]: Addison-Wesley, 2003. FIELDS, Duane; KOLB, Mark; Web development with Java Server Pages. [S. l.]: Manning Publications, 2000. GEARY, David. Core JSTL: mastering the JSP Standard Tag Library. [S. l.]: Prentice Hall, 2002. HALL, Marty. Core Servlets and JavaServer Pages. [S. l.]: Prentice Hall, [200?]. HALL, Marty. More Servlets and JavaServer Pages. [S. l.]: Pearson Education, [200?]. HORSTMANN, Cay S. Big Java. Porto Alegre: Artmed Bookman: 2004. HORSTMANN, Cay; CORNELL, Gary. Core JAVA 2. Volume I – Fundamentos. 7 ed. Editora Alta Books, 2005. KURNIAWAN, Budi. Java for web with Servlets, JSP and EJB: a developer’s guide to J2EE solutions. [S. l.]: New Riders, 2002. Linguagens de Programação II.indb 315 7/12/2006 14:01:23 Universidade do Sul de Santa Catarina SIERRA, Kathy; BASHMAN, Brian; BATES, Bert. Head first Servlets and JSP. [S. l.]: O’Reilly, 2004. SIERRA, Kathy; BATES, Bert. Java use a cabeça. Alta Books: 2005. SILVA, Ivan José de Mecenas. Java 2: fundamentos Swing e JDBC. Rio de Janeiro: Editora Alta Books, 2003. SOARES, Walace. MySQL: conceitos e aplicações. São Paulo: Erica, 2002. THOMPSON, Marco Aurélio. Java 2 & banco de dados. São Paulo, Érica: 2002. Sites de Referência http://jakarta.apache.org/taglibs/ (Site da implementação de referência da especificação JSTL) http://java.sun.com/docs//books/tutorial/uiswing/components/tabbedpane.html (How to Use Tabbed Panes) http://java.sun.com/docs/books/tutorial/uiswing/components/button.html (How to Use Buttons, CheckBoxes and Radio Buttons) http://java.sun.com/docs/books/tutorial/uiswing/components/panel.html (Como usar Panels) http://java.sun.com/docs/books/tutorial/uiswing/index.html (Creating a GUI with JFC/Swing) http://java.sun.com/products/jsp/ (Site da especificação Java Server Pages (JSP)) http://java.sun.com/products/jsp/jstl/ (Site da especificação JSTL) http://java.sun.com/products/servlet/ (Site oficial da Sun sobre a tecnologia Java Servlets) http://servlets.com/ (Site com muito material sobre a tecnologia Java Servlets) http://tomcat.apache.org/ (Site oficial do projeto Apache Tomcat) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/ (Swing The Book) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter10html/ (List) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter3html/ (Frames, Panels, and Borders) http://www.csie.ntu.edu.tw/~piaip/docs/Swing/Chapter9html/ (ComboBox) http://www.inf.pucrs.br/~flash/lapro2/lapro2_eventos.pdf (Tratamento de eventos) http://www.jcp.org/aboutJava/communityprocess/final/jsr154/index.html (Site da especificação dos Java Servlets) http://www.netbeans.org/ (IDE NetBeans – Ferramenta com recurso para criação de GUI) http://www.w3.org/CGI/ (Site do consórcio W3C sobre a tecnologia CGI) http://www.w3.org/Protocols/ (Site do consórcio W3C sobre o protocolo http) 316 Linguagens de Programação II.indb 316 7/12/2006 14:01:23 Sobre os professores conteudistas Andréa Sabedra Bordin é graduada em Análise de Sistemas pela UCPel, Especialista em Sistemas de Informação, Mestre em Ciência da Computação e Doutoranda em Engenharia e Gestão do Conhecimentos pela UFSC. Professora dos cursos de Sistemas de Informação, Ciência da Computação e de Tecnólogo em Web Design e Programação da Unisul. Também é analista de Sistemas do Instituto Stela. Andrik Dimitrii Braga de Albuquerque nasceu em Rio Branco, AC. Formado em Ciência da Computação pela Universidade do Vale do Itajaí. Atualmente é Programador Junior no Instituto Stela e atua como instrutor no curso seqüencial de Desenvolvimento de aplicação web utilizando a tecnologia Java na Universidade do Sul de Santa Catarina Unidade Tubarão. Marcelo Medeiros é formado em Ciências da Computação pela Universidade Regional de Blumenau, leciona na Unisul, nos cursos de Ciência da Computação, Sistemas de Informação e Engenharia Elétrica, desde 1995. Desenvolve junto a Unisul o projeto de pré-incubadora tecnológica, na qual os alunos recebem um acompanhamento técnico de dois anos na criação da sua empresa, funcionando desta forma como uma extensão ao aluno na sua formação de empreendedor. Na área específica de computação, desenvolve projetos nas áreas de banco de dados e apresentação de produtos em 3D e monitoramento de imagens através de câmeras e sistemas de vídeo por rede, chamados de NVS. É mestrando no curso de Ciência da Linguagem da referida universidade (UNISUL), na qual desenvolve um projeto de análise da fundamentação dos cursos de Ciências da Computação, como cursos de formação humana, e não apenas exatas. Linguagens de Programação II.indb 317 7/12/2006 14:01:23 Linguagens de Programação II.indb 318 7/12/2006 14:01:23 Respostas e comentários das atividades de auto-avaliação UNIDADE 1 1) Resposta Pessoal. 2) Código da aplicação: public interface CalculoFiguras{ public abstract double calculaArea(); //os modicadores public abstract não são obrigatórios } //superclasse Quadrilátero implementa a interface CalculoFiguras public abstract class Quadrilatero implements CalculoFiguras { private int base, altura; //atributos e métodos public Quadrilatero(){ base=0; altura=0; } public void setBase(int base){ this.base = base; } public void setAltura(int altura){ this.altura = altura; } public int getBase(){ return this.base; } public int getAltura(){ return this.altura; } } //subclasse Trapézio estende a classe Quadrilátero public class Trapezio extends Quadrilatero{ private int basem; Linguagens de Programação II.indb 319 //atributos e métodos 7/12/2006 14:01:23 Universidade do Sul de Santa Catarina public Trapezio(){ basem=0; } public void setBaseM(int basem){ this.basem = basem; } public int getBaseM(){ return this.basem; } public double calculaArea(){ return ((getBase()+this.basem)/2)*getAltura(); } } //subclasse Retângulo estende a classe Quadrilátero public class Retangulo extends Quadrilatero{ public double calculaArea(){ return getBase()*getAltura(); } } public class TestaInterface{ public static void main(String args[]){ Trapezio t = new Trapezio(); t.setBase(4); t.setBaseM(2); t.setAltura(3); System.out.println(“Area do Trapezio “ + t.calculaArea()); Retangulo r = new Retangulo(); r.setBase(5); r.setAltura(6); System.out.println(“Area do Retangulo “ + r.calculaArea()); } } 320 Linguagens de Programação II.indb 320 7/12/2006 14:01:23 Linguagens de Programação II UNIDADE 2 Código da aplicação: import java.awt.FlowLayout; import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JLabel; //classe do componente de rótulo (label). Exibe texto e imagem import javax.swing.JTextField; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JButton; public class GuiJAtivUnid2 extends JFrame{ private JLabel labelNu1; private JLabel labelNu2, labelNu3; private JTextField textfieldNu1; private JTextField textfieldNu2,textfieldNu3; private JLabel labelResultado,labelSituacao; private JButton buttonResultado; public GuiJAtivUnid2(){ super(“Exemplo JTextField”); setLayout(new FlowLayout()); labelNu1 = new JLabel(“Nota 1”); labelNu1.setToolTipText(“Digite a primeira nota”); add(labelNu1); textfieldNu1 = new JTextField(5); add(textfieldNu1); labelNu2 = new JLabel(“Nota 2”); labelNu2.setToolTipText(“Digite a segunda nota”); add(labelNu2); textfieldNu2 = new JTextField(5); add(textfieldNu2); labelNu3 = new JLabel(“Nota 3”); labelNu3.setToolTipText(“Digite a terceira nota”); add(labelNu3); textfieldNu3 = new JTextField(5); add(textfieldNu3); buttonResultado = new JButton(“Media”); add(buttonResultado); TrataEventoBotao trataevento = new TrataEventoBotao(); buttonResultado.addActionListener(trataevento); labelResultado = new JLabel(“”); add(labelResultado); 321 Linguagens de Programação II.indb 321 7/12/2006 14:01:24 Universidade do Sul de Santa Catarina labelSituacao = new JLabel(“”); add(labelSituacao); } private class TrataEventoBotao implements ActionListener{ public void actionPerformed(ActionEvent event){ labelResultado.setText(Double.toString((Double.parseDouble(textfieldNu1.getText())+Double. parseDouble(textfieldNu2.getText())+Double.parseDouble(textfieldNu3.getText()))/3)); if (Double.parseDouble(labelResultado.getText()) >= 7.0) labelSituacao.setText(“Aprovado”); else if ((Double.parseDouble(labelResultado.getText()) >= 2.0) && (Double.parseDouble( labelResultado.getText()) < 7.0)) labelSituacao.setText(“Exame”); else labelSituacao.setText(“Reprovado”); } } public static void main(String arg[]){ GuiJAtivUnid2 guiativ = new GuiJAtivUnid2(); guiativ.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guiativ.setSize(275,280); guiativ.setVisible(true); } } 322 Linguagens de Programação II.indb 322 7/12/2006 14:01:24 Linguagens de Programação II UNIDADE 3 Código da atividade: import java.awt.FlowLayout; //classe do gerenciador de layout import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JTextField; //classe do componente de texto import javax.swing.JLabel; //classe do componente de texto import javax.swing.JRadioButton; //classe do componente botão de rádio import javax.swing.ButtonGroup; //classe do agrupador de botões de rádio import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; //interface que trato o evento do componente JRadioButton import java.awt.event.ItemEvent; //classe do evento gerado pelo componente JRadioButton import java.awt.Font; public class GuiJAtivUnid3 extends JFrame{ private JLabel label1; private JLabel label2; private JLabel label3; private JLabel label4; private JTextField textfield1; private JTextField textfield2; private JTextField textfield3;; private JRadioButton radioVis; private JRadioButton radioPra; private ButtonGroup grupoRadio; public GuiJAtivUnid3(){ super(“Calculo de Desconto”); setLayout(new FlowLayout()); //configura o layout do frame label1 = new JLabel(“Total Bruto da Compra”); textfield1 = new JTextField(20); add(label1); add(textfield1); //adiciona textfield ao frame label2 = new JLabel(“Forma de Pagamento”); radioVis = new JRadioButton(“A vista”);//cria o primeiro componente JRadioButton radioPra = new JRadioButton(“A prazo”);//cria o segundo componente TrataEventoRadio trataradio = new TrataEventoRadio(); radioVis.addItemListener(trataradio); radioPra.addItemListener(trataradio); add(label2); //adiciona ao frame add(radioVis); add(radioPra); grupoRadio = new ButtonGroup(); //cria ButtonGroup - componente agrupador dos botões de radio grupoRadio.add(radioVis); //adiciona cada JRadioButton ao ButtonGroup grupoRadio.add(radioPra); 323 Linguagens de Programação II.indb 323 7/12/2006 14:01:24 Universidade do Sul de Santa Catarina label3 = new JLabel(“Desconto”); textfield2 = new JTextField(20); label3.setVisible(false); textfield2.setVisible(false); add(label3); add(textfield2); //adiciona textfield ao frame label4 = new JLabel(“Total Liquido da Compra”); textfield3 = new JTextField(20); add(label4); add(textfield3); //adiciona textfield ao frame textfield2.addActionListener(new TrataEventoTextField()); } //fim do construtor private class TrataEventoRadio implements ItemListener{ public void itemStateChanged(ItemEvent event){ if (event.getSource() == radioVis){ label3.setVisible(true); textfield2.setVisible(true); } else textfield3.setText(textfield1.getText()) ; } } //fim da classe interna private class TrataEventoTextField implements ActionListener{ public void actionPerformed(ActionEvent event){ if (radioVis.isSelected()) textfield3.setText(Double.toString(Double.parseDouble(textfield1. getText()) - ( Double.parseDouble(textfield1.getText())*Double.parseDouble(textfield2. getText())/100))); } } //fim da classe interna public static void main(String arg[]){ GuiJAtivUnid3 guiativ = new GuiJAtivUnid3(); guiativ.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guiativ.setSize(275,280); guiativ.setVisible(true); } } //fim da classe de primeiro nível 324 Linguagens de Programação II.indb 324 7/12/2006 14:01:24 Linguagens de Programação II UNIDADE 4 1) Código da atividade: import java.awt.FlowLayout; //classe do gerenciador de layout import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JTextField; //classe do componente de texto import javax.swing.JLabel; //classe do componente de texto import javax.swing.JRadioButton; //classe do componente botão de rádio import javax.swing.ButtonGroup; //classe do agrupador de botões de rádio import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; //interface que trato o evento do componente JRadioButton import java.awt.event.ItemEvent; //classe do evento gerado pelo componente JRadioButton import java.awt.Font; public class GuiJAtivUnid4 extends JFrame{ private JLabel label1; private JLabel label2; private JLabel label3; private JLabel label4; private JTextField textfield1; private JTextField textfield2; private JTextField textfield3;; private JRadioButton radioVis; private JRadioButton radioPra; private ButtonGroup grupoRadio; public GuiJAtivUnid4(){ super(“Calculo de Desconto”); setLayout(new FlowLayout()); //configura o layout do frame label1 = new JLabel(“Total Bruto da Compra”); textfield1 = new JTextField(20); add(label1); add(textfield1); //adiciona textfield ao frame label2 = new JLabel(“Forma de Pagamento”); radioVis = new JRadioButton(“A vista”);//cria o primeiro componente JRadioButton radioPra = new JRadioButton(“A prazo”);//cria o segundo componente TrataEventoRadio trataradio = new TrataEventoRadio(); radioVis.addItemListener(trataradio); radioPra.addItemListener(trataradio); add(label2); //adiciona ao frame add(radioVis); add(radioPra); grupoRadio = new ButtonGroup(); //cria ButtonGroup - componente agrupador dos botões de radio grupoRadio.add(radioVis); //adiciona cada JRadioButton ao ButtonGroup grupoRadio.add(radioPra); 325 Linguagens de Programação II.indb 325 7/12/2006 14:01:24 Universidade do Sul de Santa Catarina label3 = new JLabel(“Desconto”); textfield2 = new JTextField(20); label3.setVisible(false); textfield2.setVisible(false); add(label3); add(textfield2); //adiciona textfield ao frame label4 = new JLabel(“Total Liquido da Compra”); textfield3 = new JTextField(20); add(label4); add(textfield3); //adiciona textfield ao frame textfield2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { if (radioVis.isSelected()) textfield3.setText(Double.toString(Double.parseDouble(textfield1.getText()) - ( Double. parseDouble(textfield1.getText())*Double.parseDouble(textfield2.getText())/100))); } }); } //fim do construtor private class TrataEventoRadio implements ItemListener{ public void itemStateChanged(ItemEvent event){ if (event.getSource() == radioVis){ label3.setVisible(true); textfield2.setVisible(true); } else textfield3.setText(textfield1.getText()) ; } } //fim da classe interna public static void main(String arg[]){ GuiJAtivUnid4 guiativ = new GuiJAtivUnid4(); guiativ.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guiativ.setSize(275,280); guiativ.setVisible(true); } } //fim da classe de primeiro nível 326 Linguagens de Programação II.indb 326 7/12/2006 14:01:24 Linguagens de Programação II 2) Código da atividade: import java.awt.GridLayout; //classe do gerenciador de layout import javax.swing.JFrame; //classe que fornece os recursos básicos de uma janela import javax.swing.JTextField; //classe do componente de texto import javax.swing.JLabel; //classe do componente de texto import javax.swing.JRadioButton; //classe do componente botão de rádio import javax.swing.ButtonGroup; //classe do agrupador de botões de rádio import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.ItemListener; //interface que trato o evento do componente JRadioButton import java.awt.event.ItemEvent; //classe do evento gerado pelo componente JRadioButton import java.awt.Font; import java.awt.Container; public class GuiJAtiv2Unid4 extends JFrame{ private JLabel private JLabel private JLabel private JLabel label1; label2; label3; label4, label9, label10;// label 9 e 10 existem somente para serem inseridos nas celulas vazias private JTextField textfield1; private JTextField textfield2; private JTextField textfield3; private JRadioButton radioVis; private JRadioButton radioPra; private ButtonGroup grupoRadio; private Container container; public GuiJAtiv2Unid4(){ super(“Calculo de Desconto”); container = getContentPane(); // obtém painel de conteúdo container.setLayout( new GridLayout(4,3,1,1) ); // configura o layout JFrame label1 = new JLabel(“Total Bruto da Compra”); textfield1 = new JTextField(20); container.add(label1); container.add(textfield1); //adiciona textfield ao frame label9 = new JLabel(); container.add(label9); label2 = new JLabel(“Forma de Pagamento”); radioVis = new JRadioButton(“A vista”);//cria o primeiro componente JRadioButton radioPra = new JRadioButton(“A prazo”);//cria o segundo componente TrataEventoRadio trataradio = new TrataEventoRadio(); radioVis.addItemListener(trataradio); radioPra.addItemListener(trataradio); container.add(label2); //adiciona ao frame container.add(radioVis); container.add(radioPra); 327 Linguagens de Programação II.indb 327 7/12/2006 14:01:24 Universidade do Sul de Santa Catarina grupoRadio = new ButtonGroup(); //cria ButtonGroup - componente agrupador dos botões de radio grupoRadio.add(radioVis); //adiciona cada JRadioButton ao ButtonGroup grupoRadio.add(radioPra); label3 = new JLabel(“Desconto”); textfield2 = new JTextField(20); label10 = new JLabel(); label3.setVisible(false); textfield2.setVisible(false); container.add(label3); container.add(textfield2); //adiciona textfield ao frame container.add(label10); label4 = new JLabel(“Total Liquido da Compra”); textfield3 = new JTextField(20); container.add(label4); container.add(textfield3); //adiciona textfield ao frame textfield2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { if (radioVis.isSelected()) textfield3.setText(Double.toString(Double.parseDouble(textfield1.getText()) - ( Double. parseDouble(textfield1.getText())*Double.parseDouble(textfield2.getText())/100))); } }); } //fim do construtor private class TrataEventoRadio implements ItemListener{ public void itemStateChanged(ItemEvent event){ if (event.getSource() == radioVis){ label3.setVisible(true); textfield2.setVisible(true); } else textfield3.setText(textfield1.getText()) ; } } //fim da classe interna public static void main(String arg[]){ GuiJAtiv2Unid4 guiativ = new GuiJAtiv2Unid4(); guiativ.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); guiativ.setSize(450,160); guiativ.setVisible(true); } } //fim da classe de primeiro nível 328 Linguagens de Programação II.indb 328 7/12/2006 14:01:25 Linguagens de Programação II UNIDADE 5 1) Código da atividade: 1) Código da atividade: import java.awt.*; import javax.swing.*; import java.awt.event.*; public class GuiJTabbedPaneAtiv1Unid5 extends JFrame { private JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.BOTTOM); private JPanel cadastroPanel = new JPanel(); private JPanel consultaPanel = new JPanel(); private JLabel labelNome,labelEndereco,labelCidade; private JTextField textfieldNome,textfieldEndereco,textfieldCidade; private JButton buttons[] = new JButton[ 4 ]; // array de botões private final String names[] = { “Salvar”, “Editar”, “Deletar”, “Sair”}; public GuiJTabbedPaneAtiv1Unid5() { tabbedPane.setTabPlacement(JTabbedPane.TOP); // local das abas cadastroPanel.setLayout(new BorderLayout()); labelNome = new JLabel(“Nome”); labelEndereco = new JLabel(“Endereço”); labelCidade = new JLabel(“Cidade”); textfieldNome = new JTextField(30); textfieldEndereco = new JTextField(30); textfieldCidade = new JTextField(30); JPanel buttonJPanel = new JPanel(new GridLayout( 0, 4)); // cria JPanel dos botoes // cria e adiciona botões ao panel for ( int count = 0; count < buttons.length; count++ ) { buttons[ count ] = new JButton( names [ count ] ) ; buttonJPanel.add( buttons[ count ] ); // adiciona botão ao painel } JPanel labelPane = new JPanel(new GridLayout(0,1)); // cria JPanel dos labels labelPane.add(labelNome); //adiciona label´s ao panel labelPane.add(labelEndereco); labelPane.add(labelCidade); JPanel fieldPane = new JPanel(new GridLayout(0,1));// cria JPanel dos textedit fieldPane.add(textfieldNome); //adiciona textfield´s ao panel fieldPane.add(textfieldEndereco); fieldPane.add(textfieldCidade); cadastroPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); cadastroPanel.add(labelPane, BorderLayout.CENTER);// adiciona painel na região central cadastroPanel.add(fieldPane, BorderLayout.EAST);// adiciona painel na região Oeste cadastroPanel.add( buttonJPanel, BorderLayout.SOUTH ); // adiciona painel na região Sul 329 Linguagens de Programação II.indb 329 7/12/2006 14:01:25 Universidade do Sul de Santa Catarina tabbedPane.add(cadastroPanel, “CADASTRO”); // adiciona o painel na orelha tabbedPane.add(consultaPanel, “CONSULTA”); // adiciona o painel na orelha this.getContentPane().add(tabbedPane); } public static void main(String[] args) { GuiJTabbedPaneAtiv1Unid5 testTabbedPane = new GuiJTabbedPaneAtiv1Unid5(); testTabbedPane.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); testTabbedPane.setSize( 580, 200 ); // configura o tamanho do frame testTabbedPane.setVisible( true ); // exibe o frame } } 2) Código da atividade: import java.awt.Color; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JMenuBar; public class GuiJMenuAtiv2Unid5 extends JFrame { // construtor sem argumento para configurar a GUI public GuiJMenuAtiv2Unid5() { super( “Atividade 2 da Unidade 5” ); JMenu cadastrarMenu = new JMenu( “Cadastrar” ); // cria o menu Cadastrar cadastrarMenu.setMnemonic( ‘C’ ); // configura o mnemônico como C JMenuItem projetoItem = new JMenuItem( “Projeto” ); // cria o item de menu Projeto projetoItem.setMnemonic( ‘P’ ); // configura o mnemônico com P cadastrarMenu.add( projetoItem ); // adiciona o item Projeto ao menu Cadastrar JMenuItem particItem = new JMenuItem( “Participante” ); // cria o item Participante particItem.setMnemonic( ‘A’ ); // configura o mnemônico como A cadastrarMenu.add( particItem ); // adiciona o item Participante ao menu Cadastrar JMenuItem sairItem = new JMenuItem( “Sair” ); // cria o item Sair sairItem.setMnemonic( ‘S’ ); // configura o mnemônico como S cadastrarMenu.add( sairItem ); // adiciona o Sair exit ao menu Cadastrar 330 Linguagens de Programação II.indb 330 7/12/2006 14:01:25 Linguagens de Programação II JMenu ajudaMenu = new JMenu( “Ajuda” ); // cria o menu Ajuda ajudaMenu.setMnemonic( ‘A’ ); // configura o mnemônico como A JMenuItem sobreItem = new JMenuItem( “Sobre” ); // cria o item Sobre sobreItem.setMnemonic( ‘S’ ); // configura o mnemônico como S ajudaMenu.add( sobreItem ); // adiciona o item Sobre ao menu Ajuda JMenuBar bar = new JMenuBar(); // cria a barra de menus setJMenuBar( bar ); // adiciona uma barra de menus ao aplicativo bar.add( cadastrarMenu ); // adiciona o menu Cadastrar à barra de menus bar.add( ajudaMenu ); // adiciona o menu Ajuda à barra de menus getContentPane().setBackground( Color.BLUE ); // configura o fundo } // fim do construtor public static void main( String args[] ) { GuiJMenuAtiv2Unid5 menu = new GuiJMenuAtiv2Unid5(); menu.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); menu.setSize( 580, 200 ); // configura o tamanho do frame menu.setVisible( true ); // exibe o frame } // fim de main } // fim da classe UNIDADE 6 1) Esse tema vem sendo discutido há muito tempo por especialistas da área e tem se tornado um tema polêmico. O processo de criação de um sistema computacional em alguns momentos pode assustar o cliente final, dando a impressão de que a ferramenta possa vir a substituí-lo, representando para ele uma forma de desemprego. Para que isso não ocorra, é necessário que o especialista em informática deixe claro ao usuário que a informática é uma ferramenta auxiliar para ajudá-lo nas tarefas do dia-a-dia, mas nunca uma ferramenta que possa vir a substituí-lo. 2) O desenvolvimento de software possui muitas particularidades, principalmente porque não existe um produto que possa ser apresentado ao cliente. O desenvolvimento possui etapas bem definidas e, até que se chegue à implementação, não há o que se apresentar ao cliente. Desta forma, a relação entre os desenvolvedores e o cliente deve ser de transparência, confiança e cordialidade. Ele deve se sentir seguro com relação ao que ele contratou e com o que ele terá como produto final. Durante a fase de implementação é muito comum que se apresente ao cliente pequenas versões do produto final para sua prévia aprovação. Estas pequenas versões são chamadas de protótipos, que além de verificar se o projeto está no rumo certo, permitem que o cliente tenha um contato mais direto com o produto esperado. 331 Linguagens de Programação II.indb 331 7/12/2006 14:01:25 Universidade do Sul de Santa Catarina UNIDADE 7 1) O tratamento de erro no Java através do try-catch é uma ferramenta essencial e, em muitos casos, obrigatória. Diferentemente de algumas linguagens em que o tratamento de exceção é uma opção do programador, no Java isto não existe. A finalidade do tratamento de exceção é evitar que o sistema gere um erro fatal que venha a travar por completo o software ou, até mesmo, o sistema operacional do computador. 2) Não. A classe apenas representa as regras que o programador ou analista de sistemas determinaram ao fazer o levantamento de dados. Se a análise for realizada de forma inconsistente, a classe representará esta inconsistência. Por isso, o ponto principal de qualquer projeto computacional é o levantamento de requisitos, para fundamentar o que a implementação deverá fazer e de que forma será codificado. UNIDADE 8 1) Sim. Como a conexão com o banco de dados em Java esta relacionada ao driver de conexão usado, é possível que uma classe seja a mais genérica possível, permitindo que o driver de conexão e a forma de conexão sejam definidas na construção da classe. UNIDADE 9 Sim. A base de qualquer aplicação em Java são as classes de representação e de regras de negócio. Porém, estas classes podem ser utilizadas na criação de aplicações Java para web ou Java Server Page. UNIDADE 10 Não apresenta atividades de auto-avaliação. UNIDADE 11 1) GCI (Commom Gateway Interface). 2) GET e POST. 3) Servlet Container. 332 Linguagens de Programação II.indb 332 7/12/2006 14:01:25 Linguagens de Programação II UNIDADE 12 1) Deve ser implementado no mínimo um dos seguintes métodos: doGet, doPost, doPut, doDelete, doTrace, doOptions, sempre se tomando o cuidado para implementar o método que é especificado nas páginas que irão enviar a requisição. 2) Por meio do elemento servlet-mapping no arquivo web.xml 3) javax.servlet.http.HttpServletRequest e javax.servlet.http.HttpServletResponse, respectivamente. 4) Esse exercício seguirá a mesma filosofia do exemplo apresentado na seção Sessões. Você deve criar uma classe contato com os seguintes campos: nome, email e telefone. O passo seguinte é desenvolver dois servlets: um ficará responsável por salvar os contatos banco de dados e o outro irá ter a função de listar todos os contatos cadastrados. Para finalizar a aplicação você deve criar um projeto com a estrutura de diretórios de aplicações web e efetuar a instalação da aplicação no servidor (diretório webapps do tomcat). UNIDADE 13 1) <%! Conteúdo da declaração %>, <%= conteúdo da expressão %>, <% conteúdo do scriptlet %>. 2) As páginas JSP antes de serem executadas, são compiladas e transformadas em Servlets, ou seja, uma página JSP é um Servlet. 3) Utilizando a ação <jsp:useBean>, essa ação permite que você utilize em JavaBean nas suas páginas JSP. UNIDADE 14 1) <c:if>, <c:choose>, <c:when> e <c:otherwise>. 2) <c:foEach> e <c:forTokens>. 3) ${nomeDoObjeto}. UNIDADE 15 1) No arquivo web.xml foi inserido para cada Servlet o elemento <servletmapping> que possui dois sub-elementos <servlet-name> e <url-pattern> que são os responsáveis por estar realizando o mapeamento dos Servlets da aplicação. 2) O padrão Data Access Object (DAO) isola em classes específicas todo código relacionado ao acesso a banco de dados. 333 Linguagens de Programação II.indb 333 7/12/2006 14:01:25 Linguagens de Programação II.indb 334 7/12/2006 14:01:26