Vous êtes sur la page 1sur 58

Aplicaes de Linguagem de Programao Orientada a Objetos

Mdulo 1 AWT (Abstract Window Toolkit) e Swing


Componentes
Os componentes, tambm chamados de widgets (windows gadgets, ou dispositivos de janelas) so os elementos construtivos das interfaces grficas de usurio ou GUIs, isto , so botes, caixas de entrada de texto, caixas de seleo, menus, barras de rolagem, etc., que compem qualquer aplicativo visual. Tambm existem componentes no visuais destinados a oferecer suporte aos demais componentes, como prover acesso a dados ou outras tarefas com as quais o usurio do aplicativo no interaja diretamente. A figura abaixo apresenta um exemplo de GUI:

Java oferece uma ampla biblioteca de componentes GUI e de capacidades grficas na forma de classes, pertencentes aos pacotes java.awt e javax.swing, que representam os frameworks (ou conjuntos de classes) responsveis pela composio dos elementos visuais em um aplicativo.

AWT
A AWT constitui a primeira biblioteca de componentes visuais do Java que permitem a construo de aplicaes GUI, capaz de ser utilizada em grande parte dos sistemas operacionais. A AWT funciona como uma casca entre o componente do sistema nativo e seu equivalente representado pela classe correspondente da biblioteca. Assim, uma aplicao Java AWT que contenha um boto usar o componente nativo para botes onde a aplicao executada. Mesmo que a aparncia do componente apresente ligeira diferena entre um sistema operacional e outro para o mesmo aplicativo, o comportamento e funcionamento durante a operao sero os mesmos. No entanto, isso exige um mecanismo razoavelmente complexo e pesado de troca de mensagens entre o sistema operacional e a JVM (mquina virtual Java), o que reduz o desempenho dos componentes AWT (da serem chamados de componentes pesados ou heavy-weight components). Alm disso, a quantidade de componentes disponveis relativamente pequena e a construo de novos componentes torna-se complexa ou dependente da plataforma. A classe abstrata Component a base para a construo de todos os componentes GUI oferecidos pelo Java no pacote java.awt. Essa classe oferece a infra-estrutura necessria para a criao de objetos que possuam uma representao grfica, as quais podero ser exibidas num ambiente grfico e com as quais o usurio poder interagir. Sendo uma classe abstrata, 2

Component no pode ser instanciada diretamente, mas sendo a classe-base comum de todos os componentes da biblioteca AWT, possibilita por meio do polimorfismo o tratamento generalizado dos componentes derivados. Com a API (Application Programming Interface ou Interface de Programao de Aplicativos) da classe Component possvel determinar tamanho, cores, fonte e cursor utilizados pelo componente, alm do seu estado de funcionamento, posio e visibilidade. Em particular, a classe Component a base para a construo de outra classe abstrata especial denominada Container, a qual representa um compartimento onde outros componentes podem ser adicionados e posicionados, cuja API oferece facilidades para incluso e remoo de componentes. Classes derivadas de Container tambm so containers, isto , tambm podem conter outros componentes, tais como janelas e painis. Atualmente a AWT est integrada JFC (Java Foundation Classes), um conjunto de bibliotecas que engloba a prpria AWT, o Swing e o Java 2D. A JFC foi desenvolvida para a construo de aplicativos GUI e tambm grficas voltadas para diferentes plataformas operacionais, cujo destaque o Swing, uma outra famlia de componentes.

Swing
Como comentado, o uso do AWT dependente da plataforma; portanto, us-la no fcil e essa biblioteca no est livre de bugs. Os componentes da biblioteca Swing so mais fceis de utilizar e esto muito mais bem implementados, mas alguns de seus componentes ainda necessitam de classes da biblioteca AWT. A famlia de componentes Swing uma parte importante da JFC que engloba: Componentes Swing uma nova famlia de componentes com funcionalidade ampliada e grande capacidade de configurao; Suporte para mltiplos Pluggable Look and Feel d aos programas Java a capacidade de utilizarem diferentes aparncias visuais, tais como peles (skins) adaptadas ou no ao ambiente operacional utilizado; Acessibilidade permite o uso integrado de tecnologias para auxlio de portadores de necessidades especiais, tais como monitores e teclados diferenciados; Java 2D um pacote de classes para desenho 2D de grficos, texto e imagens de alta qualidade; Suporte para Drag and Drop oferece capacidade de arrastar e soltar entre aplicaes Java e aplicaes nativas. Alm de oferecer um conjunto muito mais amplo e verstil, os componentes Swing so 100% Java e assim no utilizam cdigo nativo tal como a famlia AWT, constituindo deste modo componentes leves (ou light-weight components). A classe JComponent do pacote javax.swing oferece a infra-estrutura para a maior parte dos componentes Swing. Por sua vez, a classe JComponent uma subclasse da classe Container, 3

do pacote java.awt, uma classe abstrata que oferece a estrutura para construo de componentes que podem conter outros componentes. Em virtude disso, a estratgia de representao (ou renderizao) utilizada no Swing diferenciada, sendo dividida em trs partes: a representao do componente em si, a representao da borda do componente e a representao dos componentes nele contidos. A figura abaixo apresenta o diagrama da hierarquia de classes da biblioteca Swing e respectivas dependncias com a biblioteca AWT.
java.awt.Container JComponent

Texto
JComboBox JTextComponent JTextArea JEditorPane

Menus
JMenuBar JPopupMenu

AbstractButton JMenuItem JMenu

Widgets
JLabel JButton JList JToggleButton JTree JCheckBox JToolBar JRadioButton JTable JSlider JScrollBar JToolTip JProgressBar

JCheckBoxMenuItem JTextPane JRadioButtonMenuItem JTextField JSeparator JPasswordField

java.awt.Panel

Janelas de nvel mais alto


JWindow

Sub-janelas
java.awt.Applet JPanel JApplet JViewPort JInternalFrame JScrollPane JPane JRootPane JSliptPane JTabbedPane JLayeredPane JOptionPane

java.awt.Applet

java.awt.Frame java.awt.Dialog

JFrame JDialog

Como uma interface grfica trabalha


Programas com interface grfica de usurio (GUI) so controlados por eventos. Isto significa que o programa reage s aes do usurio; estas aes so chamadas de eventos. Exemplos de eventos podem ser: o pressionar de uma tecla do teclado, mover o mouse, pressionar um boto ou selecionar um item de menu. Um programa com uma GUI possui uma pequena fase de iniciao na qual a GUI construda, mas ainda no exibida. Algumas outras aes (no relacionadas aos componentes visuais) tambm so executadas. Esta fase no controlada por eventos e no possvel a interao com 4

o usurio. Depois desta fase a GUI apresentada na tela e o programa passa a ser controlado por eventos. Obviamente, queremos que o programa reaja somente a alguns tipos de eventos, no todos. O programador precisa especificar quem sero os eventos aos quais o programa dever reagir e, claro, quais as reaes que dever ter para cada evento. Em Java isto feito acrescentando-se os chamados listeners, ou observadores de eventos, que so interfaces que ficam aguardando a ocorrncia de determinados tipos de eventos. O observador, ento, executa a ao desejada por meio de seus mtodos. Os eventos so processados na seqncia em que ocorrem, sob o controle de um despachante de eventos que os organizam em fila. Existem muitos tipos de eventos em Java associados a diferentes fontes de eventos, tais como botes, menus ou o mouse. Os eventos contm informaes sobre o que aconteceu, isto , quem disparou o evento (se um boto ou um item de menu) e onde ele ocorreu (em quais coordenadas do mouse, por exemplo). Estas so as informaes exploradas pelo observador. O diagrama da figura abaixo indica como se d este processo. Programa GUI

Mtodos de notificao Acionam Observadores de eventos

Gera eventos Despachante de eventos

Enfileira os eventos e notifica

Cada componente da interface um objeto de uma classe distinta. O mesmo acontece com cada tipo de evento, que um objeto de uma classe particular, da mesma forma que cada observador (listener) uma interface que especifica um tipo particular de receptor de eventos. As classes e interfaces disponveis no modelo de eventos da AWT esto no pacote java.awt.event. Todos os eventos da AWT possuem uma raiz comum que a classe abstrata AWTEvent, existindo tipos diferentes de eventos responsveis pelo encapsulamento de informaes relativas s diferentes aes possveis. Todos os componentes Swing so capazes de produzir eventos dos seguintes tipos: ComponentEvent, FocusEvent, KeyEvent e MouseEvent. Tais eventos, respectivamente, sinalizam a alterao do tamanho, posio e visibilidade do componente, as mudanas de foco, o acionamento de teclas via teclado e a utilizao do mouse sobre o componente, necessitando de tratamento pelos seus respectivos observadores: ComponentListener, FocusListener,

KeyListener e MouseListener. A tabela a seguir apresenta os eventos adicionais gerados pelos principais componentes Swing.
UndoableEditEvent ListSelectionEvent DocumentEvent WindowEvent ChangeEvent ActionEvent

CaretEvent

Classes

ItemEvent

Outros eventos

JButton JCheckBox JColorChooser JComboBox JDialog JEditorPane JFileChooser JFrame JInternalFrame JList JMenu JMenuItem JOptionPane JPasswordField JPopupMenu JProgress JRadioButton JSlider JSpinner JTabbedPane JTable JTextArea JTextField JTextPane JToggleButton JTree JViewPort

* * * * *

* * *

* * * * * * * InternalFrameEvent * MenuEvent MenuDragMouseEvent, MenuKeyEvent PopupMenuEvent HyperlinkEvent

* * *

* * * * * * * *

* * * * * * * * * * * *

TableModelEvent, TableColumnModelEvent, CellEditorEvent HyperlinkEvent TreeExpansionEvent, TreeWillExpandEvent, TreeModelEvent, TreeSelectionEvent

* *

Os eventos tpicos do Swing so aqueles produzidos pelos componentes mais usados pela grande maioria das aplicaes, cujo tratamento usualmente requisitado: ActionEvent evento semntico que indica a ocorrncia de alguma ao predefinida em um componente. Corresponde ao acionamento de botes (JButton) e itens de menu (JMenuItem), mas pode ser disparado por outros componentes tal como no acionamento da tecla ENTER em uma caixa de texto (JTextField). Seu tratamento realizado por implementao da interface ActionListener; CaretEvent notifica as classes interessadas que a posio do cursor de edio de um componente de texto sofreu modificao. produzido por componentes deste tipo, tais como JTextField e JTextArea. Seu tratamento realizado por implementaes da interface CaretListener; ChangeEvent permite avisar s classes interessadas que ocorreu alguma mudana no componente associado, tal como o posicionamento de um controle deslizante JSlider ou 6

troca de aba em um JTabbedPane. Seu tratamento realizado por implementaes da interface ChangeListener; DocumentEvent constitui uma interface para notificao de modificaes em documentos (contedo de componentes de texto). So produzidos de modo especializado por JTextField, JTextArea e outros. Seu tratamento exige a implementao da interface DocumentListener; UndoableEditEvent indica a ocorrncia de uma operao que pode ser desfeita e cujo tratamento se d por meio da interface UndoableEditListener; ItemEvent evento semntico que indica a seleo ou remoo da seleo de um componente. Corresponde a seleo de caixas de opo (JCheckBox), botes de opo (JRadioButton) ou itens de combos e listas (respectivamente JComboBox e JList). Seu tratamento realizado por implementaes da interface ItemListener; ListSelectionEvent caracteriza a mudana de seleo em uma caixa de lista (JList) ou tabela (JTable). Seu tratamento realizado por implementao da interface ListSelectionListener; WindowEvent evento de baixo nvel que indica a alterao do estado de uma janela. O tratamento deste evento se d por meio de implementaes da interface

WindowListener. Os eventos semnticos so aqueles que tm significados bem definidos e cujos tratamentos so independentes de plataforma. Tambm so considerados como eventos de alto nvel. J os demais eventos, chamados de baixo nvel, possuem tratamentos que, s vezes, precisam considerar detalhes especficos da plataforma, sendo portanto de implementao mais complexa. O tratamento de eventos no Java relativamente simples. Para um evento qualquer, aqui denominado XEvent, seu tratamento sempre acontece por meio de uma interface XListener, a qual ser includa e removida respectivamente pelos mtodos addXListener(XListener) e removeXListener(XListener). Na interface XListener comum que os mtodos a serem implementados tenham como prefixo o nome do evento (embora existam vrias excees). A tabela abaixo relaciona os principais eventos, suas interfaces ou classes adaptadoras e respectivos mtodos do Swing:
Evento ActionEvent CaretEvent ChangeEvent ComponentEvent Interface ou Adaptador ActionListener CaretListener ChangeListener ComponentListener ComponentAdapter DocumentListener FocusListener FocusAdapter ItemListener KeyListener KeyAdapter Mtodos actionPerformed(ActionEvent) caretUpdate(CaretEvent) stateChanged(ChangeEvent) componentHidden(ComponentEvent) componentMoved(ComponentEvent) componentResized(ComponentEvent) componentShow(ComponentEvent) changedUpdate(DocumentEvent) insertUpdate(DocumentEvent) removeUpdate(DocumentEvent) focusGained(FocusEvent) focusLost(FocusEvent) itemStateChanged(ItemEvent) keyPressed(KeyEvent) keyReleased(KeyEvent)

DocumentEvent FocusEvent ItemEvent KeyEvent

ListSelectionEvent

ListSelectionListener MouseListener

MouseEvent

MouseAdapter MouseMotionListener MouseMotionAdapter MouseWheelListener UndoableEditListener WindowListener WindowAdapter

MouseWheelEvent UndoableEditEvent

WindowEvent

keyTyped(KeyEvent) valueChanged(ListSelectionEvent) mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseDragged(MouseEvent) mouseMoved(MouseEvent) mouseWheelMoved(MouseWheelEvent) undoableEditHappened(UndoableEditEvent) windowActivated(WindowEvent) windowClosed(WindowEvent) windowClosing(WindowEvent) windowDeactivated(WindowEvent) windowDeiconified(WindowEvent) windowIconified(WindowEvent) windowOpened(WindowEvent)

Mdulo 2 Swing parte 1: Criao de objetos via cdigo


Construindo uma aplicao grfica
Quando se decide pela construo de uma aplicao grfica, necessrio um projeto da interface para a aplicao, ou seja, preciso determinar quais tarefas devem ser realizadas pela interface, quais componentes sero utilizados, qual o objetivo de seu uso e qual a disposio desejada para tais componentes. Dessa maneira, possvel dizer que a representao de uma aplicao grfica envolve seis passos simples, os quais devem ser repetidos para cada janela pretendida para a aplicao: 1. Esboo da janela: desenho da janela pretendido que inclui disposio dos componentes (leiaute), identificao e tipo dos componentes, especificao das aes do usurio e reaes correspondentes; 2. Implementao de uma subclasse JFrame: construo de uma subclasse de JFrame para cada janela; 3. Declarao dos componentes: declarao dos componentes ativos como campos privados da classe criada e, opcionalmente, dos componentes no ativos; 4. Representao do construtor: definio de construtor capaz de organizar os componentes na interface e registrar os eventos necessrios; 5. Programao dos processadores de eventos (event listeners): representao dos mtodos que processaro os eventos selecionados; 6. Incio da aplicao GUI: caso a janela seja a principal da aplicao (a primeira janela a ser utilizada), adequado incluir o mtodo main(String[] args).

Frames
Os elementos bsicos de qualquer sistema operacional grfico so as janelas, que so reas retangulares nas quais texto, imagens ou outras informaes podem ser exibidas. As janelas tambm podem conter elementos de interao com usurios, como menus, botes ou reas para 8

entrada de textos. Muitos outros componentes grficos no podem ser exibidos isoladamente, sendo necessrio que sejam colocados dentro de uma janela. A aparncia final de uma janela depender do sistema operacional utilizado, especialmente a largura e o tipo de borda ao redor de uma janela. A posio e a cor dos botes podem variar. Em Java, o termo frame (moldura) usado para aquilo que genericamente denominado janela. No Swing, os frames so representados pela classe JFrame. Um frame uma rea retangular com uma barra de ttulo no topo. A barra de ttulo tambm contm botes para fechar, maximizar e minimizar a janela. Como comentado, o tipo e a posio desses botes dependem da plataforma (Windows, MacOS, Linux, Solaris, etc.). Abaixo da barra de ttulo existe uma rea na qual outros componentes grficos podem ser embutidos. Esta rea dividida em duas partes: um espao para uma barra de menu na parte superior e o painel de contedo, logo abaixo. O painel de contedo pode conter diversos componentes grficos embutidos. Se no for includa uma barra de menu, ento o painel de contedo expandido para o espao vazio deixado pela ausncia da barra de menu. As funes bsicas como redimensionamento ou movimentao do frame com o mouse so automaticamente fornecidas e no precisam ser programadas pelo programador. Existe um outro componente chamado window na biblioteca Swing, mas este componente no possui moldura, isto , no possui uma barra de ttulo, uma borda nem botes de fechar, maximizar ou minimizar. A figura abaixo mostra a estrutura de um frame:
Ttulo Espao para a barra de menu
_

Painel de contedo

O construtor padro do frame o JFrame(), que gera um frame sem ttulo. Gerar aqui significa que a informao para desenhar-se o frame fornecida; entretanto, o frame no exibido na tela. Isto obtido chamando-se o mtodo setVisible. O mtodo setVisible(boolean b) torna o frame visvel se b for true. Se b for false, o frame ocultado da tela, mas a informao utilizada para desenh-lo no destruda. Assim, se b for true novamente, o frame tornar-se- visvel na tela mais uma vez, ou seja, no ser necessrio chamar o construtor uma segunda vez.

O mtodo setTitle(String title) ajusta o ttulo na barra de ttulo do frame com o valor passado como argumento em title. O mtodo setSize(int width, int height) ajusta a largura do frame de acordo com o valor passado como argumento em width e a altura com o valor passado em height. O mtodo setLocation(int horizontal, int vertical) posiciona o canto superior esquerdo do frame na tela de acordo com os valores passados em horizontal e vertical. O mtodo pack() redimensiona o frame de modo que se ajuste firmemente ao redor dos componentes embutidos em seu painel de contedo. Finalmente, o mtodo setDefaultCloseOperation(int operation) determina o que acontece se o boto de fechar do frame for pressionado. Neste caso, pode-se utilizar a opo JFrame.EXIT_ON_CLOSE como parmetro passado ao argumento operation.

Panels e layouts
Embutiremos agora outro componente grfico em um frame. Os componentes usados chamam-se panels (painis). Panels so componentes retangulares, que servem a dois propsitos: podem ser usados como se fossem uma tela onde se pode desenhar ou podem ser usados como compartimentos (containers) para embutir mais componentes grficos. No Swing a classe JPanel representa um panel. Abaixo temos seu construtor e alguns mtodos: JPanel() o construtor. O tamanho do panel ajustado para valores padronizados, 10 por 10 pixels na maioria dos sistemas. setBackground(Color c) ajusta a cor de fundo do panel. A classe Color vem da biblioteca da AWT. Assim, algumas cores so pr-definidas, isto , vermelho ser Color.red. Por padro a cor de fundo cinza (grey). setPreferredSize(Dimension d) ajusta o tamanho do panel. A classe Dimension vem da biblioteca da AWT. O construtor possui a sintaxe Dimension(int width, int height). Tanto width quanto height esto em pixels. importante lembrar que estes valores so apenas recomendaes para o tamanho de um componente. Dependendo do tamanho de outros componentes, o sistema em tempo de execuo poder escolher valores diferentes para eles! Os valores realmente usados so determinados por um LayoutManager (gerenciador de leiaute) em tempo de execuo. Esta flexibilidade importante ao Java para que seja independente de plataforma. Componentes grficos so embutidos da seguinte maneira: chamemos o componente que queremos embutir de componente filho (child component). Aqueles componentes do Swing capazes de embutir outros possuem um mtodo add (adicionar). Ento, para embutir um componente filho (childComp) em um componente pai (parentComp), a sintaxe utilizada : parentComp.add(childComp)

10

Vamos agora especificar como os componentes so acomodados no painel de contedo. A fim de ser uma plataforma independente, os projetistas do Java deram alguma flexibilidade ao sistema grfico. O programador apenas especifica a estrutura de arranjo dos componentes, no suas posies absolutas. Por exemplo, especifica-se que o componente A est direita do componente B ao invs de definir que o componente A est na posio (x, y). Em tempo de execuo, as posies dos componentes que so determinadas. Isto feito pelo chamado layout manager (gerenciador de leiaute) que est associado ao componente pai. Existem diferentes gerenciadores de leiaute pr-definidos e o programador pode definir os seus prprios. Um JFrame possui por padro um BorderLayout; mais precisamente o painel de contedo possui um gerenciador de leiaute do tipo BorderLayout. Ele permite que o usurio posicione um (grande) componente central e at quatro componentes nas bordas. As posies so determinadas pelas constantes CENTER, NORTH, SOUTH, EAST e WEST. Estas constantes esto definidas na classe BorderLayout. Se um componente de borda no estiver presente, ento o componente central expande-se naquela direo. O componente central geralmente contm a informao principal. Os componentes de borda contm informaes extras. Para inserir um componente filho (childComp) dentro do painel de contedo na posio pos, usamos o mtodo: this.getContentPane().add(childComp, pos) Onde pos uma das seguintes constantes: BorderLayout.CENTER, BorderLayout.NORTH, BorderLayout.SOUTH, BorderLayout.EAST ou BorderLayout.WEST. A figura abaixo apresenta a distribuio dos componentes ao redor do frame.
CNorth

CWest

CEast

CCenter

CSouth

Vejamos agora mais dois gerenciadores de leiaute: o gerenciador de leiaute por fluxo (FlowLayout) e o gerenciador de leiaute por grade (GridLayout). Os leiautes no esto restritos a frames. Todo componente Swing no qual outros componentes possam ser embutidos (os chamados compartimentos ou containers) possui um leiaute. O leiaute padro uma borda. Para que se possa alterar o leiaute de um componente pai parentComp para outro leiaute newLayout usa-se o comando: parentComp.setLayout(newLayout) Se um componente tem um leiaute de fluxo ento os componentes embutidos so dispostos em fila nica da esquerda para a direita. Se uma linha estiver completa, a prxima iniciada. Leiaute em linha (normalmente) respeita as dimenses dos componentes embutidos. A ordem de chamada do parentComp.add(child) determina a ordem dos componentes embutidos no componente pai. A altura de uma linha determinada em tempo de execuo, verificando-se 11

todos os componentes daquela linha, conforme indicado na figura abaixo, onde os componentes C3 e C5 que esto determinando a altura de cada uma das duas linhas presentes no frame.

C1

C2

C3

C4

C5

A seguir, alguns construtores do FlowLayout: FlowLayout() FlowLayout(int align) FlowLayout(int align, int hdist, int vdist) O primeiro construtor gera um leiaute que, por padro, deixa cinco pixels de distncia entre os componentes de uma linha e cinco pixels de distncia entre linhas. Complementarmente, o segundo construtor especifica o tipo de alinhamento dos componentes, onde align um destes: FlowLayout.RIGHT, FlowLayout.LEFT ou FlowLayout.CENTER Isto determina quais componentes em cada linha estaro empacotados direita, esquerda ou quais estaro centralizados. O terceiro construtor, alm disso, tambm especifica a distncia hdist horizontal entre os componentes de uma linha e a distncia vdist vertical entre linhas. O terceiro gerenciador de leiaute a ser descrito o GridLayout, que ordena os componentes em uma grade. O componente pai (em nosso exemplo, o painel de contedo) dividido em l x c clulas retangulares, onde c o nmero de clulas por linha e l o nmero de linhas. Todas as clulas tm o mesmo tamanho. Os componentes ficam embutidos dentro das clulas em fila nica da esquerda para a direita. Se houver mais clulas que componentes embutidos o gerenciador de leiaute tentar preencher todas as linhas o mais separado possvel e poder gerar menos que c colunas! Se houver menos clulas que componentes ento mais colunas so adicionadas. Basicamente o gerenciador de leiaute por grade ignora o nmero de colunas. A fim de ter um nmero fixo c > 0 de colunas, o nmero de linhas deve ser ajustado para l = 0 e o nmero de colunas para c. Assim, sempre haver c colunas e o nmero de linhas depender do nmero de componentes embutidos. A figura abaixo exemplifica o uso do gerenciador de leiaute por grade.
C1 C2 C3

C4

C5

Vazio

12

Exerccios de Laboratrio do mdulo 2


1. Crie a classe abaixo, referente representao de um frame principal. Teste os diferentes mtodos dessa classe no mtodo main, alterando o tamanho do frame, posio na tela e o ttulo. Crie mais um mtodo exibeFrame de modo que seja possvel tambm ao programador usurio dessa classe alterar as dimenses da janela, que est limitada no construtor a 200 por 200 pixels.
package br.unip.cc4si4.ALPOO; import javax.swing.JFrame; public class JanelaPrincipal extends JFrame{ public JanelaPrincipal(){ this.setSize(200,200); this.setLocation(200,200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } //Torna o frame visivel public void exibeFrame(){ this.setVisible(true); } //Torna o frame visivel e define o texto do titulo public void exibeFrame(String titulo){ this.setTitle(titulo); this.setVisible(true); } //Torna o frame visivel e define o texto do titulo //e a posicao da janela public void exibeFrame(String titulo, int x, int y){ this.setTitle(titulo); this.setLocation(x,y); this.setVisible(true); } //Torna o frame invisivel public void ocultaFrame(){ this.setVisible(false); } //Cria e exibe o frame public static void main(String[] args){ new JanelaPrincipal().exibeFrame("Janela Principal", 150, 150); } }

2. Crie a classe abaixo, referente representao de um panel.


package br.unip.cc4si4.ALPOO; import java.awt.*; import javax.swing.JPanel; public class PanelColorido extends JPanel{ //Gera um JPanel com cor de fundo cor public PanelColorido(Color cor){ this.setBackground(cor); } //Gera um JPanel com cor de fundo cor, //largura e altura public PanelColorido(Color cor,int largura,int altura){ this.setPreferredSize(new Dimension(largura,altura)); this.setBackground(cor); } }

3. Altere o construtor da classe JanelaPrincipal conforme indicado abaixo e inclua tambm o seguinte import em seu cabealho: import java.awt.*;
public JanelaPrincipal(){ this.setSize(200,200); this.setLocation(200,200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); PanelColorido PCWest = new PanelColorido(Color.white,50,20); PanelColorido PCEast = new PanelColorido(Color.red); PanelColorido PCNorth = new PanelColorido(Color.yellow); PanelColorido PCSouth = new PanelColorido(Color.green); PanelColorido PCCenter = new PanelColorido(Color.blue); this.getContentPane().add(PCWest,BorderLayout.WEST); this.getContentPane().add(PCEast,BorderLayout.EAST); this.getContentPane().add(PCNorth,BorderLayout.NORTH);

13

this.getContentPane().add(PCSouth,BorderLayout.SOUTH); this.getContentPane().add(PCCenter,BorderLayout.CENTER); }

Se voc quisesse que o programador usurio dessa classe fosse capaz de alterar a cor de fundo, que complementao de cdigo seria necessria na classe JanelaPrincipal? 4. Altere novamente o construtor da classe JanelaPrincipal conforme indicado abaixo:
public JanelaPrincipal(LayoutManager layout){ this.getContentPane().setLayout(layout); this.setSize(200,200); this.setLocation(200,200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); PanelColorido PC1 = new PanelColorido(Color.red ,30,30); PanelColorido PC2 = new PanelColorido(Color.yellow ,40,20); PanelColorido PC3 = new PanelColorido(Color.green); PanelColorido PC4 = new PanelColorido(Color.blue); PanelColorido PC5 = new PanelColorido(Color.white,80,20); this.getContentPane().add(PC1); this.getContentPane().add(PC2); this.getContentPane().add(PC3); this.getContentPane().add(PC4); this.getContentPane().add(PC5); }

Altere tambm o mtodo main conforme indicado a seguir:


public static void main(String[] args){ FlowLayout flowLayout1 = new FlowLayout(); JanelaPrincipal flow1Frame = new JanelaPrincipal(flowLayout1); flow1Frame.exibeFrame("Leiaute por fluxo 1",60,60); FlowLayout flowLayout2 = new FlowLayout(FlowLayout.LEFT,40,30); JanelaPrincipal flow2Frame = new JanelaPrincipal(flowLayout2); flow2Frame.exibeFrame("Leiaute por fluxo 2",300,60); GridLayout gridLayout = new GridLayout(2,4); JanelaPrincipal gridFrame = new JanelaPrincipal(gridLayout); gridFrame.exibeFrame("Leiaute por grade",540,60); }

O que acontece com a distribuio dos componentes embutidos no frame se alterarmos suas dimenses de 200 por 200 para 230 por 200 pixels? Porque o construtor recebe como argumento um gerenciador de leiaute? Esse construtor poderia ter um gerenciador de leiaute sem precisar receber um como argumento? Explique para que serve cada um dos argumentos (se houver) dos 3 objetos gerenciadores de leiaute criados no mtodo main.

Mdulo 3 Swing parte 2: Utilizao de objetos visualmente


Labels
Um label (rtulo) um componente retangular que exibe texto que no pode ser editado pelo usurio (mas pode ser alterado pelo programa). A classe JLabel cria rtulos no Swing. Aqui apresentamos dois construtores e alguns mtodos: public JLabel(String texto) public JLabel(ImageIcon imagem)

public String getText() public void setText(String texto) public void setText(String texto, int alinhamento) 14

public void setForeground(Color cor) public void setBackground(Color cor) public void setOpaque(boolean b) JLabel(String texto) constri um rtulo que exibe o texto: texto; JLabel(ImageIcon imagem) constri um rtulo que exibe a imagem: imagem; getText() devolve o texto atualmente exibido no rtulo como uma String; setText(String texto) substitui o texto atualmente exibido no rtulo pelo texto: texto. O novo texto instantaneamente apresentado no rtulo; setText(String texto, int alinhamento) substitui o texto atualmente exibido no rtulo pelo texto: texto. Ele tambm ajusta o alinhamento do texto esquerda, direita ou ao centro. Os valores possveis para alinhamento so encontrados na classe SwingConstants; por exemplo, use SwingConstants.CENTER para centralizar o texto no rtulo; setForeground(Color cor) ajusta a cor do texto para cor; setBackground(Color cor) ajusta a cor do fundo do rtulo para cor. Note que rtulos so transparentes por padro e suas cores de fundo no so visveis. De fato, observa-se que a cor do componente pai a que se destaca. Para mudar a cor de fundo de um rtulo primeiro deve-se torn-lo opaco usando-se o mtodo setOpaque; setOpaque(boolean b) torna o rtulo transparente se b for false e opaco se b for true.

Buttons
Buttons (botes) so reas retangulares, geralmente com uma linha delineando-as, que tal como os rtulos podem exibir texto. Eles diferem dos rtulos porque podem disparar eventos. Um evento ocorre sempre que um boto pressionado. O sistema em tempo de execuo do Java monitora botes e reconhece quando um evento desse tipo ocorre. Note que um boto no necessariamente pressionado clicando-o com o mouse, pode haver tambm um dedo pressionando-o em uma tela sensvel a toque (as chamadas touch screens). A fim de detectar quando um boto pressionado, algum fica de olho nele; esse algum o listener (observador), um componente no grfico da biblioteca AWT. O observador tem que estar associado ao boto para que possa monitor-lo. Se ocorrer um evento com o boto em tempo de execuo, o sistema informar o observador, que poder ento analisar o evento e dar incio a alguma ao especfica. A classe JButton representa botes no Swing. Apresentaremos apenas o construtor e o mtodo que associa um observador ao boto: public JButton(String texto); public void addActionListener(ActionListener observador); JButton(String texto) constri um boto que contm o texto: texto; addActionListener(ActionListener observador) adiciona um observador que detectar eventos ocorridos no boto. 15

Menus
Menus so normalmente muito utilizados como componentes de frames. Eles esto organizados hierarquicamente. O componente mais elevado dessa hierarquia a barra de menu, uma rea retangular localizada abaixo da barra de ttulo de um frame e acima do painel de contedo. Os componentes intermedirios so os menus. Um menu aparece como um texto na barra de menu. Quando algum clica em um desses textos, o menu selecionado se descortina, apresentando diversos itens de menu, que esto na base da hieraquia. Os itens de menu so componentes que disparam eventos. Eles podem ser considerados como um tipo especial de boto. De fato, tal como os botes, os itens de menu fazem uso de observadores de eventos para monitor-los. s vezes necessrio desabilitar determinados itens de menu por algum perodo de tempo. Um item de menu desabilitado no dispara nenhuma ao quando clicado. Em muitas plataformas o texto de um item de menu desabilitado aparece esmaecido em relao aos itens habilitados. A barra de menu representada pela classe JMenuBar: JMenuBar() add(JMenu menu) JMenuBar() constri uma barra de menu; add(JMenu menu) adiciona um menu em uma barra de menu. Os menus so adicionados barra de menu da esquerda para a direita na ordem dos comandos add. Para adicionar uma barra de menu em um frame, usamos o seguinte mtodo da classe JFrame: setJMenuBar(JMenuBar barraDeMenu) Note que existem dois mtodos distintos: setJMenuBar e setMenuBar para adicionar um JMenuBar (usando Swing) e um MenuBar (usando AWT). Da classe JMenu precisamos do construtor que recebe o ttulo do menu em uma string e mtodos para adicionar itens de menu ou separadores, que so linhas horizontais que separam os itens de menu em blocos: JMenu(String tituloDoMenu) add(JMenuItem itemDeMenu) addSeparator() Em um menu, os itens de menu ou separadores so inseridos do topo para a base na ordem dos comandos add. Finalmente, da classe JMenuItem necessitamos do construtor que recebe o ttulo do item em uma string e um mtodo para associar um observador de eventos ao item de menu. Os itens de menu comportam-se de modo muito semelhante aos botes. Em particular, o observador de eventos (action listener) automaticamente informado quando o item clicado. O observador ento inicia as aes desejadas. Finalmente precisamos de um mtodo para habilitar ou desabilitar um item de menu: 16

JMenuItem(String textoDoItem) addActionListener(ActionListener observador) setEnabled(boolean b) A chamada setEnabled(false) desabilita um item de menu. O item aparece com um texto suavizado e qualquer observador associado a ele no mais notificado cada vez que o item for clicado. Assim, um item desabilitado no dispara qualquer reao na aplicao. Chamando setEnabled(true) habilitar o item de menu novamente. O texto torna-se bem destacado e os observadores associados ao item de menu passam a ser notificados dos eventos.

Exerccios de Laboratrio do mdulo 3


Neste laboratrio teremos o primeiro exemplo de uma aplicao GUI real. Real aqui significa que teremos um programa que interage com o usurio. A interao realizada usando botes e itens de menu em uma tela grfica. Apesar de o programa ser muito simples, gostaramos de introduzir o conceito de uma abordagem modelo-viso-controle (model-view-control ou MVC) neste ponto. A parte referente ao modelo do programa, no grfica, lida com o armazenamento, manuteno e manipulao de dados. A parte referente viso exibe os dados e fornece os componentes necessrios interao com o usurio, neste caso, botes e menu. A parte referente ao controle, tambm no grfica, assegura que as aes do usurio resultaro nas respostas desejadas dadas pelo programa. A parte de controle a ponte entre o modelo e a viso. A separao em estruturas de modelo, viso e controle geralmente uma abordagem fundamental para o desenvolvimento de uma aplicao rpida e com sucesso. Ela tambm auxilia os programadores iniciantes a melhor reconhecer os conceitos essenciais e suas interconexes. Em Java, tal separao facilmente obtida usando-se orientao a objetos, isto , diferentes classes ou ao menos diferentes mtodos para diferentes partes. Em aplicaes complexas, pacotes separados (com seus conjuntos de classes) podem ser usados para partes diferentes da aplicao. Vamos ento iniciar a especificao da interface grfica de usurio que queremos representar. Queremos montar um contador. Ele est especificado como uma estrutura de dados abstrata. O contador possui uma varivel chamada valor do tipo inteiro. Inicialmente ela vale zero. O contador permite trs operaes: Incremento incrementa o valor do contador de 1; Decremento decrementa o valor do contador de 1; Restauro reinicia o valor do contador para 0.

Vamos agora definir a aparncia da tela e como ela funcionar. A GUI que temos em mente deve exibir o valor atual do contador e permitir que o usurio possa increment-lo, decrement-lo ou restaur-lo. Para esta finalidade teremos trs botes. Pressionando o primeiro (incrementar) com o mouse, incrementaremos o contador. Pressionando o segundo (decrementar) decrementaremos o contador e pressionando o terceiro (restaurar) zeraremos o contador. Estas opes devero 17

estar disponveis tambm no menu. Assim, teremos um menu Opes com os seguintes itens de menu: Incrementar, Decrementar e Restaurar. E um segundo menu Programa com o item de menu Sair, para finalizar a aplicao. A figura abaixo mostra como queremos que a GUI se parea.
Aplicao 1 Opes Incrementar Decrementar Restaurar Incrementar Rtulo contendo o valor do contador Programa _ x

Decrementar

Restaurar

Vamos agora programar um contador em uma classe no grfica que chamaremos de Contador. Esta classe ter apenas uma varivel inteira chamada valor que ser iniciada em zero no construtor, conforme exigido pela especificao. A varivel valor privada, de modo que outras classes s possam manipul-la atravs dos mtodos fornecidos pela classe Contador. Representaremos as trs operaes requeridas na especificao em trs mtodos com nomes bvios: incrementa(), decrementa() e restaura()e um quarto mtodo, getValor(), para ler o contedo da varivel valor. Abaixo temos a listagem da classe:
package br.unip.cc4si4.ALPOO; public class Contador { private int valor; //O constructor incia o contador em zero. public Contador() { valor = 0; } public void incrementa(){ valor++; } public void decrementa(){ valor--; } public void restaura(){ valor = 0; } public int getValor(){ return valor; } }

Cuidaremos agora da parte grfica. Existem muitas maneiras de se arranjar os componentes (botes, rtulos e menu). Uma delas seria colar os botes, o rtulo e o menu diretamente no painel de contedo do frame. Utilizaremos aqui uma abordagem diferente: aplicaremos no painel de contedo do frame um panel intermedirio que ficar responsvel por embutir os botes, o rtulo e o menu. A classe responsvel por essa disposio de elementos ser chamada PainelDoContador. Assim, PainelDoContador que ser colada ao frame. A vantagem 18

desta abordagem que se pode reutilizar a classe PainelDoContador como um mdulo pronto em outras aplicaes. Reutilizao de cdigo, portanto. Veja na figura abaixo a disposio desses elementos na aplicao:
Aplicao 1 _ x

JFrame JMenuBar JPanel

Opes

Programa

JLabel
Incrementar

Rtulo contendo o valor do contador

Decrementar

JButton
Restaurar

Abaixo, temos a listagem da classe PainelDoContador:


package br.unip.cc4si4.ALPOO; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JMenuBar; import javax.swing.JButton; import javax.swing.JLabel; import java.awt.BorderLayout; import javax.swing.SwingConstants; public class PainelDoContador extends JPanel { private Contador contador; private JLabel valorDoLabel; public PainelDoContador() { //Cria um objeto contador e define o //gerenciador de leiaute como sendo BorderLayout. contador = new Contador(); BorderLayout bordLay = new BorderLayout(); this.setLayout(bordLay); //Cria uma barra de menu e a adiciona ao panel JMenuBar barraDeMenu = new JMenuBar(); this.add(barraDeMenu,BorderLayout.NORTH); //Cria e adiciona os menus barra de menu JMenu opcoes = new JMenu("Opes"); JMenu programa = new JMenu("Programa"); barraDeMenu.add(opcoes); barraDeMenu.add(programa); //Cria os itens de menu e os adiciona aos menus JMenuItem incrementar = new JMenuItem("Incrementar"); JMenuItem decrementar = new JMenuItem("Decrementar"); JMenuItem restaurar = new JMenuItem("Restaurar"); JMenuItem sair = new JMenuItem("Sair"); opcoes.add(incrementar); opcoes.add(decrementar); opcoes.addSeparator(); opcoes.add(restaurar); programa.add(sair); //Cria os botes de incrementar, decrementar e restaurar //e cria o rotulo que exibe o valor do contador. JButton botaoIncrementa = new JButton("Incrementar"); JButton botaoDecrementa = new JButton("Decrementar"); JButton botaoRestaura = new JButton("Restaurar"); valorDoLabel = new JLabel(""+contador.getValor(),SwingConstants.CENTER); //Adiciona os botes e o rtulo no panel utilizando as regras //de posicionamento de elementos do gerenciador de objetos BorderLayout. this.add(botaoIncrementa,BorderLayout.WEST); this.add(botaoDecrementa,BorderLayout.EAST); this.add(botaoRestaura,BorderLayout.SOUTH); this.add(valorDoLabel,BorderLayout.CENTER); } public void incrementa(){

19

contador.incrementa(); valorDoLabel.setText(""+contador.getValor()); } public void decrementa(){ contador.decrementar(); valorDoLabel.setText(""+contador.getValor()); } public void restaura(){ contador.restaurar(); valorDoLabel.setText(""+contador.getValor()); } }

E em seguida, a listagem da classe JanelaDoContador, que o frame responsvel por embutir o panel PainelDoContador:
package br.unip.cc4si4.ALPOO; import javax.swing.JFrame; import java.awt.BorderLayout; public class JanelaDoContador extends JFrame { public JanelaDoContador(){ //Define o tamanho e a posio do frame na tela this.setSize(300,200); this.setLocation(200,200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Cria e insere um panel do tipo PainelDoContador PainelDoContador pdc = new PainelDoContador(); this.getContentPane().add(pdc,BorderLayout.CENTER); } public void exibeFrame(String title){ this.setTitle(title); this.setVisible(true); } public void ocultaFrame(){ this.setVisible(false); } public static void main(String[] args) { //Cria um objeto frame e o exibe na tela JanelaDoContador jdc = new JanelaDoContador(); jdc.exibeFrame("Aplicao 1"); } }

Se voc rodar o programa, observar que ao clicar nos botes ou nos itens de menu nada acontece. A conexo entre as aes do usurio (como pressionar um boto) e a aplicao estabelecida pelos observadores (listeners). Estes so componentes no-grficos fornecidos pela biblioteca AWT: java.awt.events.*. Existem diferentes observadores para diferentes tipos de eventos (pressionar um boto, mover o mouse, etc.). Observadores so, em geral, interfaces e no classes. Vamos comear descrevendo como o conceito de um observador normalmente funciona. Alguns componentes do Swing so capazes de disparar eventos. Por exemplo, um boto pode ser pressionado ou um item de menu pode ser selecionado. Tais eventos so automaticamente notificados pelo Java ao sistema em tempo de execuo. Agora, o programador pode criar um observador e associ-lo ao componente grfico, digamos um boto. Assim, o observador fica aguardando at que o boto seja pressionado e tome as aes necessrias se isto acontecer. O sistema em tempo de execuo notifica o observador se o boto foi pressionado. A notificao feita chamando-se um mtodo especfico do observador. O nome deste mtodo predefinido na interface do observador. O programador tem que caracterizar este mtodo inserindo o cdigo que ser executado em resposta ao boto que foi pressionado.

20

Em nossa aplicao, o contador tem que ser incrementado ou decrementado em resposta ao respectivo boto pressionado. O observador portanto associado aos trs botes, ou seja, ele monitora todos. Se um boto for pressionado o observador avisado. A fim de tomar a ao apropriada ele tem que saber qual boto foi pressionado. Esta informao fornecida pelo sistema em tempo de execuo na forma de um objeto do tipo ActionEvent. Esta classe tambm se encontra na biblioteca AWT (em java.awt.events). Um objeto do tipo ActionEvent contm informao acerca do evento notificado pelo sistema em tempo de execuo. Para este exerccio, criaremos um observadores na classe ObservadorPainel. Esta classe representa a interface Java ActionListener. A criao da classe requerer ainda a definio de um nico mtodo actionPerformed (ao executada): public void actionPerformed(ActionEvent evento) Este o mtodo chamado pelo sistema em tempo de execuo sempre que um boto for pressionado ou um item de menu for selecionado. Voc no ter que chamar esse mtodo, alis nem deve. O sistema em tempo de execuo tambm gera uma ao evento e a passa como um argumento do mtodo actionPerformed. Este cdigo ento executado em resposta ao pressionar de um boto. A informao contida na ao evento pode ser utilizada para obter mais informaes sobre o qu disparou o evento. A listagem abaixo da classe ObservadorPainel:
package br.unip.cc4si4.ALPOO; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class ObservadorPainel implements ActionListener{ private PainelDoContador pdc; public ObservadorPainel(PainelDoContador painel) { pdc = painel; } //Este mtodo chamado pelo sistema em tempo de execuo. //Voc deve adicionar o cdigo a ser executado //em resposta ao evento. public void actionPerformed(ActionEvent evento){ //Incio do seu cdigo: String actionCommand = evento.getActionCommand(); if(actionCommand.equals("Incrementar")){ pdc.incrementa(); } else if(actionCommand.equals("Decrementar")){ pdc.decrementa(); } else if(actionCommand.equals("Restaurar")){ pdc.restaura(); } else if(actionCommand.equals("Sair")){ System.exit(0); } else{ System.out.println("ERRO: ActionCommand inesperado."); } //Fim do seu cdigo } }

O corao da classe ObservadorPainel a codificao do mtodo actionPerformed. Primeiro, determinamos quais dos botes foi pressionado ou qual dos itens de menu foi selecionado. Isto feito inspecionando-se o objeto de ao evento que o mtodo actionPerformed recebeu do sistema em tempo de execuo. A linha: 21

String actionCommand = evento.getActionCommand(); Extrai o comando da ao do objeto evento. O comando da ao geralmente o texto do boto que foi pressionado ou o texto do item de menu. Em nosso caso ele s pode ser Incrementar, Decrementar, Restaurar ou Sair. Para verificar qual desses textos foi obtido usamos uma estrutura if-then-else. Dependendo do resultado do teste, chamamos o mtodo incrementa(), decrementa() ou restaura() do painel, ou ainda finalizamos a aplicao. Neste ponto vemos porque ao observador dada uma referncia para um objeto PainelDoContador no construtor da classe. O observador, dessa maneira, sabe qual painel ele tem que atuar em resposta ao evento. Isto importante se tivermos diversos painis em uma aplicao. Para fazer com que o painel e o observador se comuniquem, acrescente no construtor da classe PainelDoContador as seguintes linhas de cdigo:
//Cria os observadores de botao. ObservadorPainel op = new ObservadorPainel(this); botaoIncrementa.addActionListener(op); botaoDecrementa.addActionListener(op); botaoRestaura.addActionListener(op); //Cria os observadores de menu/itens de menu. opcoes.addActionListener(op); incrementar.addActionListener(op); decrementar.addActionListener(op); restaurar.addActionListener(op); sair.addActionListener(op);

1. Desenhe o diagrama de classes do pacote br.unip.cc4si4.ALPOO, apresentando os mtodos de cada classe e as relaes entre as classes, inclusive as classes da biblioteca Swing utilizadas para gerar os diferentes componentes grficos desta aplicao.

Mdulo 4 Swing parte 3: Tratamento de eventos


Caixas de texto
Caixas de texto apresentam uma nica linha de texto. O texto pode ser editado pelo usurio. A classe JTextField representa caixas de texto no Java. Para editar um texto, clique dentro da caixa de texto e um cursor piscante aparecer. A caixa de texto automaticamente desloca o contedo na horizontal se o texto for maior que a caixa. Esta funcionalidade inerente. Caixas de texto so opacas e tm cor de fundo branca e texto preto por padro. Abaixo, o construtor e alguns mtodos: public JTextField(String texto) public String getText() public void setText(String texto) public void setForeground(Color cor) public void setBackground(Color cor) JTextField(String texto) constri uma caixa de texto que exibe texto. setText(String texto) substitui o texto atualmente exibido na caixa de texto por texto. getText() devolve o texto atualmente exibido na caixa de texto no formato String. 22

setForeground(Color cor) ajusta a cor do texto para cor. setBackground(Color cor) ajusta a cor de fundo para cor.

Botes de rdio
Botes de rdio so representados usando-se a classe JRadioButton. Um boto de rdio retangular. Ele contm uma rea circular sua esquerda e um rtulo sua direita. Botes de rdio podem ser pressionados bem como podem ser agrupados. Somente um boto de rdio pode ser pressionado de cada vez e o boto permanecer pressionado at que outro boto do grupo o seja. Um ponto preto surge dentro da rea circular do boto que for selecionado. A seguir, o construtor e alguns de seus mtodos: JRadioButton(String nomeDoBotao) setSelected(boolean pressionado) setActionCommand(String comando) String getActionCommand() JRadioButton(String nomeDoBotao) cria um boto rotulado de nomeDoBotao. setSelected(boolean pressionado) determina qual boto foi selecionado (pressionado = true) ou no (pressionado = false). No primeiro caso o ponto preto fica visvel dentro da rea circular do boto. Este mtodo utilizado inicialmente para definir qual dos botes estar pressionado antes da primeira interao com o usurio. setActionCommand(String comando) associa a string comando como uma ao de comando para o boto. Botes de rdio no so associados automaticamente a uma ao de comando. Isto porque seus rtulos geralmente recebem uma imagem e no um texto. Definimos a ao de comando ns mesmos atravs do mtodo setActionCommand. getActionCommand() devolve a ao de comando associada ao boto de rdio. Alm disso, devemos nos certificar que somente um boto ser pressionado de cada vez. Isto conseguido agrupando-se os botes. Usamos para isso a classe ButtonGroup da biblioteca AWT. Abaixo listamos o seu construtor e alguns mtodos: JButtonGroup() add(JRadioButton botao) String getSelection().getActionCommand() JButtonGroup() constri um grupo de botes mas ainda sem conter nenhum boto. add(JRadioButton botao) adiciona o boto de rdio botao ao grupo. String getSelection().getActionCommand() devolve a ao de comando do boto que estiver atualmente selecionado dentro do grupo. Uma vez os botes dentro de um grupo, somente um de cada vez pode ser pressionado. Pressionar um boto no pressionado libera o que estiver pressionado.

23

Botes de seleo
O boto de seleo pode ser utilizado para indicar conjuntos de opes em que nenhuma, uma, vrias ou todas as opes so selecionadas. Botes de seleo so representados pela classe JCheckBox. Um boto de seleo retangular e contm uma rea quadrada sua esquerda e um rtulo sua direita. Quando um boto de seleo pressionado, um sinal de verificao ( ) surge na rea quadrada do boto. A seguir, um de seus construtores: JCheckBox(String texto) JCheckBox(String texto) constri um boto de seleo rotulado de texto.

Exerccios de Laboratrio do mdulo 4


1. Construir uma aplicao que contenha um frame, um panel e, dentro deste, uma caixa de texto, um boto e dois rtulos. Esta aplicao deve ser capaz de ler uma temperatura em graus Celsius fornecida pelo usurio e convert-la em Farenheit, ao clicar o boto da aplicao. Abaixo, a listagem da classe JanelaTemperaturas:
package br.unip.cc4si4.ALPOO; import java.awt.BorderLayout; import javax.swing.JFrame; public class JanelaTemperaturas extends JFrame { public JanelaTemperaturas(){ //Define o tamanho e a posio do frame na tela this.setSize(200, 100); this.setLocation(200, 200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Cria e insere um panel do tipo PainelTemperaturas PainelTemperaturas pt = new PainelTemperaturas(); this.getContentPane().add(pt, BorderLayout.CENTER); } public void exibeFrame(String title){ this.setTitle(title); this.setVisible(true); } public static void main(String[] args){ JanelaTemperaturas jt = new JanelaTemperaturas(); jt.exibeFrame("Conversor"); } }

A seguir, a listagem do panel PainelTemperaturas:


package br.unip.cc4si4.ALPOO; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JButton; import javax.swing.JTextField; import java.awt.GridLayout; public class PainelTemperaturas extends JPanel { private JLabel rotuloCelsius, rotuloFarenheit; private JButton botaoConverteTemperatura; private JTextField caixaTextoTemperatura; public PainelTemperaturas(){ //Define o gerenciador de leiaute GridLayout gridlayout = new GridLayout(2,2,1,1); this.setLayout(gridlayout); //Cria, na sequncia indicada, uma caixa de texto //um rtulo, um boto e outro rtulo caixaTextoTemperatura = new JTextField(); rotuloCelsius = new JLabel("Celsius", JLabel.RIGHT); botaoConverteTemperatura = new JButton("Converter"); rotuloFarenheit = new JLabel("Farenheit", JLabel.RIGHT); //Acrescenta uma dica na caixa de texto e no

24

//boto para auxlio do usurio caixaTextoTemperatura.setToolTipText("Temperatura em graus Celsius"); botaoConverteTemperatura.setToolTipText("Converte Celsius para Farenheit"); //Exibe os componentes grficos no painel this.add(caixaTextoTemperatura); this.add(rotuloCelsius); this.add(botaoConverteTemperatura); this.add(rotuloFarenheit); //Insere o observador dos componentes do painel ObservadorPainelTemperaturas opt = new ObservadorPainelTemperaturas(this); //Conecta o observador aos componentes caixaTextoTemperatura.addActionListener(opt); botaoConverteTemperatura.addActionListener(opt); } //Mtodo para leitura do contedo da caixa de texto public float leTemperatura(){ try{ float temp = 1.8f*Float.parseFloat(caixaTextoTemperatura.getText()); rotuloFarenheit.setText(temp+" F"); return temp; } catch (NumberFormatException nfe) { rotuloFarenheit.setText("Valor invalido!"); return 0.0f; } } }

E por fim o observador do panel, ObservadorPainelTemperaturas:


package br.unip.cc4si4.ALPOO; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class ObservadorPainelTemperaturas implements ActionListener { //Cria um atributo privado do tipo PainelTemperaturas private PainelTemperaturas pt; //Define o construtor da classe que recebe como parmetro //o painel PainelTemperaturas public ObservadorPainelTemperaturas(PainelTemperaturas painel){ pt = painel; } //Este mtodo chamado pelo sistema em tempo de execuo //Voc deve adicionar o cdigo a ser executado em resposta ao evento public void actionPerformed(ActionEvent evento){ //Seu cdigo pt.leTemperatura(); } }

2. Construir uma aplicao que contenha dois grupos de botes: um com botes de verificao e outro com botes de rdio. Incluir tambm dois rtulos que indiquem as opes feitas pelo usurio. Utilizar um panel colado ao frame que contenha os dois grupos de botes e seus rtulos. Para esta aplicao teremos cinco classes: uma para o frame, duas para os panels e demais componentes grficos e outras duas classes contendo os observadores de eventos, um para cada panel. A listagem abaixo apresenta a classe JanelaDeBotoes, que representa o frame:
package br.unip.cc4si4.ALPOO; import javax.swing.JFrame; import java.awt.GridLayout; public class JanelaDeBotoes extends JFrame { public JanelaDeBotoes(){ //Define o tamanho e a posicao do frame na tela this.setSize(200,150); this.setLocation(200,200); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Cria e define o gerenciador de leiaute do frame GridLayout gridlayout = new GridLayout(1,2); this.setLayout(gridlayout); //Cria a insere o panel PainelBotaoDeRadio no frame PainelBotaoDeRadio pbdr = new PainelBotaoDeRadio(); this.getContentPane().add(pbdr); //Cria e insere o panel PainelBotaoDeVerificacao no frame PainelBotaoDeVerificacao pbdv = new PainelBotaoDeVerificacao(); this.getContentPane().add(pbdv);

25

} public void exibeFrame(String titulo){ this.setTitle(titulo); this.setVisible(true); } public void ocultaFrame(){ this.setVisible(false); } public static void main(String[] args){ JanelaDeBotoes jdb = new JanelaDeBotoes(); jdb.exibeFrame("Aplicao 2"); } }

A seguir, a listagem de PainelBotaoDeRadio, que gera um panel que ser colado ao frame:
package br.unip.cc4si4.ALPOO; import javax.swing.JPanel; import javax.swing.ButtonGroup; import javax.swing.JRadioButton; import javax.swing.JLabel; import java.awt.GridLayout; public class PainelBotaoDeRadio extends JPanel { private JRadioButton rb[] = new JRadioButton[3]; private JLabel botaoradio = new JLabel("Sem seleo"); public PainelBotaoDeRadio(){ //Define o gerenciador de leiaute do panel GridLayout gridleiaute = new GridLayout(4,1); this.setLayout(gridleiaute); //Cria um grupo de botes ButtonGroup bg = new ButtonGroup(); //Cria o observador dos botes de rdio ObservadorDoPainelBotaoDeRadio opbr = new ObservadorDoPainelBotaoDeRadio(this); //Cria e insere os botes de verificao no panel, o grupo de botes //bem como os seus observadores de evento for(int i=0; i<3; i++){ this.add(rb[i] = new JRadioButton("Alternativa "+(i+1))); bg.add(rb[i]); rb[i].addItemListener(opbr); } //Insere o label no panel bem como o seu observador de evento this.add(botaoradio); } //Mtodo para renomear o texto do label: botaoradio public void renomeiaBotaoRadio(String nome){ botaoradio.setText(nome); } }

Agora, a listagem de PainelBotaoDeVerificao:


package br.unip.cc4si4.ALPOO; import javax.swing.JPanel; import javax.swing.JCheckBox; import javax.swing.JLabel; import java.awt.GridLayout; public class PainelBotaoDeVerificacao extends JPanel { private JCheckBox cb[] = new JCheckBox[3]; private JLabel botaoverificacao = new JLabel("Sem seleo"); public PainelBotaoDeVerificacao(){ //Define o gerenciador de leiaute do panel GridLayout gridleiaute = new GridLayout(4,1); this.setLayout(gridleiaute); //Cria o observador de botes de verificao ObservadorDoPainelBotaoDeVerificacao opbv = new ObservadorDoPainelBotaoDeVerificacao(this); //Cria e insere os botes de verificao no panel //bem como os seus observadores de evento for(int i = 0; i<3; i++){ this.add(cb[i] = new JCheckBox("Alternativa "+(i+1))); cb[i].addItemListener(opbv); } //Insere o label no panel bem como o seu observador de evento this.add(botaoverificacao); } //Mtodo para verificar se um boto foi selecionado public boolean botaoFoiSelecionado(int i){

26

if(cb[i].isSelected()) return true; else return false; } //Mtodo para renomear o label botaoverificacao public void renomeiaBotaoVerificacao(String nome){ botaoverificacao.setText(nome); } }

Temos em seguida a listagem do observador ObservadorDoPainelBotaoDeRadio:


package br.unip.cc4si4.ALPOO; import javax.swing.JRadioButton; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; public class ObservadorDoPainelBotaoDeRadio implements ItemListener { //Cria um atributo privado do tipo PainelBotaoDeRadio private PainelBotaoDeRadio pbdr; //Define o construtor da classe que recebe como parametro //o painel PainelBotaoDeRadio public ObservadorDoPainelBotaoDeRadio(PainelBotaoDeRadio painel){ pbdr = painel; } //Este metodo e chamado pelo sistema em tempo de execucao //Voce deve adicionar o codigo a ser executado em resposta ao evento public void itemStateChanged(ItemEvent evento){ //Inicio do seu codigo: JRadioButton rb = (JRadioButton)evento.getSource(); String nomeDoBotao = rb.getText(); pbdr.renomeiaBotaoRadio("Selecao: " + nomeDoBotao.charAt(nomeDoBotao.length()-1)); //Fim do seu codigo. } }

Finalmente, a listagem do ObservadorDoPainelBotaoDeVerificacao:


package br.unip.cc4si4.ALPOO; import java.awt.event.ItemListener; import java.awt.event.ItemEvent; public class ObservadorDoPainelBotaoDeVerificacao implements ItemListener { //Cria um atributo privado do tipo PainelBotaoDeVerificacao private PainelBotaoDeVerificacao pbdv; //Define o construtor da classe que recebe como parametro //o painel PainelBotaoDeVerificacao public ObservadorDoPainelBotaoDeVerificacao(PainelBotaoDeVerificacao painel){ pbdv = painel; } //Este metodo e chamado pelo sistema em tempo de execucao //Voce deve adicionar o codigo a ser executado em resposta ao evento public void itemStateChanged(ItemEvent evento){ //Inicio do seu codigo: StringBuffer itens = new StringBuffer("Selecao: "); for(int i=0; i<3; i++){ itens.append(pbdv.botaoFoiSelecionado(i)?(i+1)+" ":""); } pbdv.renomeiaBotaoVerificacao(itens.toString()); //Fim do seu codigo. } }

3. Desafio: construir uma calculadora em Java. A calculadora deve ter: um JTextField onde o usurio visualiza os nmeros e as contas; JButtons para cada nmero e pelo menos as quatro operaes bsicas, alm de botes para limpar e corrigir, bem como um JPanel que receber os componentes grficos e ser colado ao frame, criado com um JFrame. Os botes com nmeros devem reagir s aes do teclado e somente responder a teclas numricas, ponto decimal e sinais para soma, subtrao, diviso e multiplicao. Para isso, deve-se utilizar o observador de eventos de teclado: KeyListener e criar uma classe observadora que trate os eventos gerados pelo teclado com o KeyEvent. A aplicao pode ser aprimorada com um menu, via JMenu. 27

Mdulo 5 JDBC: java.sql Conexo com Banco de Dados


SGBD (Sistema Gerenciador de Banco de Dados) um conjunto de dados que pode ser utilizado por meio de um grupo particular de programas, proporcionando um ambiente conveniente e eficiente para o armazenamento e a recuperao de informaes. Os bancos de dados tornaram-se extremamente populares e importantes no segmento empresarial, principalmente aqueles que operam segundo o modelo relacional, os quais so conhecidos tambm como SGBDR (Sistema Gerenciador de Banco de Dados Relacionais). JDBC (Java Database Connectivity) uma API definida nos pacotes java.sql e javax.sql para a conexo arbitrria de um banco de dados a um programa Java. A API JDBC um conjunto de classes e interfaces que prov um padro para tornar possvel, aos desenvolvedores de aplicaes e ferramentas, a construo de software que acesse banco de dados. Ela ainda prov acesso universal a dados para a linguagem de programao Java, permitindo o acesso a qualquer tipo de dados (bancos de dados relacionais ou no relacionais, planilhas e arquivos de dados).

Uma analogia
Uma das melhores formas de se entender os princpios bsicos da JDBC atravs de uma analogia. Suponha que tocamos um pequeno negcio que comercializa gadgets. Os gadgets so produzidos em uma fbrica, que fica alm de um rio frente do nosso comrcio. Sem um barco ou uma ponte, no h maneira de ir fbrica ou da fbrica entregar seus bens nossa loja. Esta situao anloga a um banco de dados e um programa Java: o programa Java a loja e o banco de dados a fbrica. Sem alguma coisa para ajudar, no h maneira para o programa Java fazer requisies ao banco de dados, nem o banco de dados capaz de se comunicar com o programa Java. A fim de que os produtos saiam da fbrica para a loja, seria lgico construir uma ponte sobre o rio. A pea de software correspondente ponte para permitir a comunicao entre o programa Java e o banco de dados uma interface chamada driver (controlador). A figura abaixo mostra a analogia apresentada.

A arquitetura JDBC conceitualmente semelhante ao ODBC (Open Database Connectivity), amplamente utilizado em sistemas Windows. No entanto, JDBC mais flexvel, e seu emprego independe de plataforma operacional em uso, um princpio fundamental do Java.

28

Por meio dessa API, torna-se possvel o acesso, genrico e uniforme, a qualquer SGBDR, sendo que os dados so efetivamente acessados por meio do SQL (Structured Query Language). Cabe ao programador escrever uma interface simples com os elementos da API JDBC para conectar-se ao banco de dados, escolhendo a forma de interao. Com o auxlio do SQL devero ser especificadas as operaes de consulta, de incluso, de remoo ou de alterao de dados, sem necessidade de programao adicional para a realizao destas operaes. Desta forma, o uso do SQL imprescindvel, enquanto o JDBC constitui uma interface para o acesso aos bancos de dados.

Mapeamento de tipos
Outra caracterstica importante do JDBC o mapeamento transparente dos tipos de dados existentes no banco de dados para os tipos nativos do Java oferecendo, quando necessrio, classes adicionais para esta tarefa. A tabela abaixo apresenta a correspondncia entre os tipos SQL e os tipos Java. necessrio destacar que alguns bancos de dados podem apresentar excees para tipos especficos. Tipo SQL BIGINT BINARY BIT BLOB CHAR CLOB DATE DECIMAL DOUBLE FLOAT INT, INTEGER LONGVARBINARY LONGVARCHAR NUMERIC REAL SMALLINT TIME TIMESTAMP TINYINT VARBINARY VARCHAR Tipo Java long byte[ ] boolean java.sql.Blob java.lang.String java.sql.Clob java.sql.Date java.math.BigDecimal double double int byte[ ] java.lang.String java.math.BigDecimal float short java.sql.Time java.sql.Timestamp byte byte[ ] java.lang.String

Todos os tipos comuns do SQL so equivalentes a tipos primitivos Java. Outros tipos (tais como DATE, TIME e TIMESTAMP) so suportados por classes especficas, enquanto tipos complexos, BLOB e CLOB, so suportados pelas interfaces java.sql.Blob e java.sql.Clob, cuja implementao definitiva depende do banco de dados em uso.

Componentes do JDBC
Identificam-se quatro elementos centrais na arquitetura JDBC: 29

Classes e interfaces de sua API, contidas nos pacotes java.sql e javax.sql, que constituem os elementos de interligao padronizada entre aplicaes Java e bancos de dados relacionais; Sute de testes de drivers, disponibilizada no site da Sun voltado ao JDBC, que permite avaliar as funcionalidades e a compatibilidade de drivers JDBC. Site de consulta: http://java.sun.com/products/jdbc; Drivers JDBC que representam, de fato, os mecanismos padronizados de conexo e de interao com cada banco de dados; Ponte JDBC-ODBC que possibilita o uso de drivers ODBC como drivers JDBC, permitindo o uso de banco de dados acessveis exclusivamente por meio do ODBC.

A classe DriverManager (gerenciador de driver) e os drivers JDBC so particularmente importantes. Por meio desta classe selecionado o driver apropriado para acesso ao banco de dados especfico que ser utilizado por uma aplicao. Essa classe tambm ser responsvel pela conexo inicial com o banco escolhido. Alm do DriverManager possvel utilizar um objeto javax.sql.DataSource para conexo com um banco de dados, mas isto exige que o servio JNDI (Java Naming and Directory Interface) esteja ativo na rede em uso.

Drivers e seus tipos


Um driver JDBC uma classe especial que deve representar a interface java.sql.Driver. Os drivers podem ser escritos completamente em Java, de modo que possam ser carregados dinamicamente por aplicaes ou applets. Tambm podem ser representados usando cdigo nativo, criando uma conexo para outras bibliotecas ou drivers destinados ao acesso a bancos de dados especficos. A Sun exige que um driver suporte, no mnimo, a funcionalidade prevista no padro ANSI SQL-92 para passar nos testes de compatibilidade do JDBC. Por meio de um driver, uma aplicao tem acesso a codificaes especficas das classes que so capazes de converter as requisies de operaes (comandos SQL) em aes particulares para um banco de dados, sendo responsveis pela efetiva integrao das aplicaes Java com os diversos bancos de dados. Existem quatro tipos diferentes ou categorias de drivers: 1. Ponte JDBC-ODBC (JDBC-ODBC bridge plus ODBC driver); 2. API nativa parcialmente Java (native API partial Java); 3. Cliente (JDBC-net pure Java); 4. Protocolo nativo 100% Java (native protocol pure Java).

A figura abaixo ilustra os tipos de drivers e o esquema geral de conexo entre um programa Java e um banco de dados via JDBC: 30

Aplicao Java / Applet JDBC API

Os drivers de protocolo nativo 100% Java so aqueles codificados integralmente em Java e que representam diretamente o protocolo proprietrio do banco de dados, convertendo as chamadas JDBC em chamadas do sistema de banco de dados locais ou remotas. Usualmente exibem desempenho superior, devido ao acesso direto s facilidades oferecidas pelos SGBDRs. So conhecidos como drivers de categoria 4. Os drivers de cliente traduzem as chamadas JDBC em outras independentes do protocolo do banco de dados. Tais chamadas so direcionadas a um servidor ou middleware (camada intermediria de software), o qual as converte para o protocolo do banco de dados. uma alternativa bastante flexvel, pois o cliente pode se manter 100% Java, enquanto o servidor ou middleware pode se conectar a mltiplos bancos. So conhecidos como drivers de categoria 3. Os drivers de API nativa parcialmente Java representam diretamente o protocolo proprietrio do banco de dados, convertendo as chamadas JDBC em chamadas do sistema do banco efetuadas por meio de sua API proprietria. Assim, requer o uso de cdigo especfico de plataforma e do banco de dados em cada mquina cliente. So conhecidos como drivers de categoria 2. Finalmente, com o uso da ponte JDBC-ODBC, torna-se possvel o uso de drivers ODBC de sistemas Windows (categoria 1) para obter o acesso aos bancos de dados que no dispem de drivers de outras categorias.

31

Sempre que possvel, devem ser empregadas solues baseadas no uso de drivers das categorias 3 e 4. O uso de drivers de categoria 1 e 2 deve ser visto como uma soluo temporria e de desempenho inferior devido ao uso de numerosas camadas entre a aplicao e o banco de dados.

A classe DriverManager
A utilizao de m banco de dados requer uma conexo estabelecida por meio de um driver adequado. A classe DriverManager responsvel por administrar e selecionar tal driver conforme o banco de dados especfico, possibilitando efetuar a conexo. A solicitao de uma conexo com um banco de dados realizada pelo mtodo getConnection(String) da classe DriverManager, que recebe uma URL (Uniform Resource Locator) no padro JDBC para indicar qual o banco de dados desejado. A classe DriverManager analisa a URL recebida e seleciona o driver apropriado para efetuar a conexo dentre a lista de drivers disponveis. Um pedido de conexo tem a forma:
try{ Connection con = DriverManager.getConnection(jdbc:hsqldb:hsql://omega/ssolar); } catch (SQLException excecao){ //Conexo no foi possvel }

Caso a conexo no seja possvel, a exceo java.sql.SQLException, de tratamento obrigatrio, lanada.

URLs JDBC
A API JDBC utiliza uma estrutura de endereamento semelhante s URLs para especificar qual banco de dados ser utilizado. Tais URLs tm a seguinte formatao: jdbc:<subprotocolo>:<subnome> O prefixo inicial jdbc indica o uso desta API. O subprotocolo a denominao do banco de dados, a qual dever ser reconhecida pelos drivers disponveis. O subnome depende do banco e, geralmente, inclui: host, onde opera o banco de dados e o nome desse banco. Mas podem incluir tambm a indicao de outro subprotocolo, portas especficas, usurios, etc. A tabela abaixo apresenta alguns formatos de URLs JDBC. SGBD MySQL Oracle Firebird PostgreSQL SQLServer ODBC URL jdbc:mysql://hostname:3306/database jdbc:oracle:thin@hostname:1526:database jdbc:firebirdsql://hostname:3050/database jdbc:postgresql://hostname:5432/database jdbc:microsoft:sqlserver://hostname:1433/database jdbc:odbc:datasource

O MySQL
MySQL um sistema de gerenciamento de banco de dados relacional de cdigo-fonte aberto e de nvel corporativo. Foi desenvolvido por uma empresa de consultoria na Sucia chamada TcX em 32

1994, encabeado por Michael Widenius e David Axmark. Eles precisavam de um sistema de banco de dados que fosse extremamente rpido e flexvel. Infelizmente, no conseguiam encontrar nada no mercado que pudesse fazer o que queriam. Ento, eles criaram o MySQL, que vagamente baseado em outro sistema de gerenciamento de bancos de dados chamado MSQL. O produto criado rpido, confivel e extremamente flexvel. utilizado em muitos lugares por todo o mundo. Universidades, provedores de Internet e organizaes sem fins lucrativos so os principais usurios do MySQL, principalmente por ser gratuito via licena GPL. Mas cada vez mais ele vem permeando o mundo dos negcios como um SGBDR confivel e rpido. Entre suas principais caractersticas, podemos destacar: Suporta praticamente qualquer plataforma atual; Pouco exigente quanto a recursos de hardware; Excelente desempenho e estabilidade; Suporta controle transacional, triggers, cursores (non-scrollable e non-updatable), stored procedures e functions; Replicao facilmente configurvel; Interfaces grficas (MySQL Toolkit) de fcil utilizao cedidas pela MySQL Inc.

O MySQL foi comprado pela Sun Microsystems em 16 de Janeiro de 2008 por U$ 1 bilho (um preo jamais visto no setor de licenas livres) e a Sun, em 20 de Abril de 2009, foi adquirida pela Oracle. Portanto, atualmente o MySQL um produto Oracle. Este ser o SGBDR utilizado para conectar-se aos aplicativos Java.

O driver do MySQL
O driver JDBC oficial para o MySQL o MySQL Connector/J. um arquivo compactado e pode ser baixado do site do MySQL. Usaremos aqui a verso 5.1 desse driver, cujo nome do arquivo : mysql-connector-java-5.1.8.zip As orientaes abaixo so baseadas no material didtico do Prof. Vladimir Camelo. Abra o arquivo com um programa de descompactao e descompacte somente o arquivo: mysql-connector-java-5.1.8-bin.jar Salve este arquivo nas pastas: C:\Program Files\Java\jdk1.6.0_11\jre\lib\ext C:\Program Files\Java\jre6\lib\ext Se o seu sistema operacional estiver em portugus, a pasta Program Files chama-se Arquivo de Programas. Altere o nome do arquivo mysql-connector-java-5.1.8-bin.jar para: mysql.jar Como indicado na figura abaixo.

33

Crie no CLASSPATH um alias (apelido) para esse arquivo. Chame o CLASSPATH acessando o boto Iniciar do Windows, depois selecione o item Painel de Controle e, na janela que se abre, selecione o cone Sistema. Ser aberta uma segunda janela, indicada abaixo esquerda. Clique no boto Variveis de ambiente (na imagem o boto est em ingls, destacado em vermelho).

Edite a varivel de ambiente CLASSPATH, destacado em vermelho na figura acima, direita.

34

Na ltima figura, na caixa de texto com o valor da varivel (destacada em vermelho) insira, aps o ltimo texto que l estiver, um ponto-e-vrgula (;) e em seguida o endereo onde se encontra o arquivo mysql.jar, ou seja, insira: C:\Program Files\Java\jdk1.6.0_11\jre\lib\ext\mysql.jar Preste ateno: se o seu Windows estiver em portugus, utilizar o nome dos diretrios existentes em lngua portuguesa e no os nomes aqui indicados em ingls, j que este exemplo est usando um Windows de lngua inglesa! Finalizados estes passos, o driver do MySQL est pronto para ser utilizado em conjunto com as aplicaes Java. Para trabalhar com o banco de dados, criando tabelas, inserindo dados, etc., utilizaremos o MySQL Toolkit, tambm disponvel no site do banco de dados. A instalao simples e segue o mesmo procedimento de qualquer programa executvel no ambiente Windows e, por esse motivo, no sero dados maiores detalhes sobre sua instalao, mas ser a ferramenta utilizada nos exerccios.

Exerccios de Laboratrio do mdulo 5


Neste exerccio criaremos um total de 4 tabelas no MySQL que sero utilizadas num aplicativo Java que ser criado posteriormente para conectar-se a elas. As tabelas, seus campos e tipos, chave primrias e estrangeiras esto indicados abaixo.
TituloID Titulo Ano Preco Ttulos Int Chave primria Varchar Int Float Pedidos Int Chave primria Int Chave estrangeira Int Chave estrangeira Date Char

ClienteID ClienteNome ClienteEndereco ClienteTelefone

Clientes Int Varchar Varchar Varchar CD Int Int Varchar

Chave primria

CDID TituloID Tipo

Chave primria Chave estrangeira

NumeroPedido ClienteID CDID DataPagamento Status

Para criar essas tabelas, acesse o banco de dados MySQL utilizando o aplicativo MySQL Administrator, que faz parte do MySQL Toolkit. Ao chamar o aplicativo, a janela abaixo se abre.

35

A conexo ALPOO foi previamente configurada. Nos computadores do laboratrio, consulte o professor para receber as informaes necessrias conexo. Uma vez inseridas as informaes, clique em OK. A janela principal do MySQL Administrator ser aberta, como se v na figura abaixo.

A criao de tabelas exige uma base de dados para isso; no MySQL Administrator isso feito selecionando-se a opo Catalogs, na janela esquerda. A seleo desse item apresenta as bases de dados j existentes, como se observa abaixo.

Bases de dados j existentes

Para criar uma nova base de dados, clique com o boto direito do mouse sobre a janela que apresenta as bases de dados existentes e, na nova janela que se abre, selecione a opo Create new schema, como destacado na figura a seguir:

36

Surgir a caixa de dilogo solicitando que informe o nome da nova base de dados, como se observa a seguir. Digite o seu nome, por exemplo, para diferenciar das bases de dados dos demais alunos.

Clique em OK para criar a base. Uma vez, criada a base, ela aparece juntos s existentes. Para criarmos nossa primeira tabela, temos duas opes: Clicar sobre o nome da base recm criada e, com o boto direito do mouse, selecionar a opo Create new table, ou; Clicarmos sobre o boto Create table. Observe a seguir as possveis opes de criao de uma tabela, destacadas em vermelho.

Qualquer que seja a seleo feita, uma janela surgir, com diversos campos a serem preenchidos. A figura abaixo apresenta como devemos definir nossa primeira tabela, que ser a Clientes. 37

Para criar um campo, basta clicar duas vezes abaixo do nome: Column Name; fazendo isto, surge uma caixa de texto com um cursor piscando, o que significa que o MySQL Administrator est aguardando a entrada do nome do novo campo a ser criado. Siga esse procedimento para cada novo campo que queira incluir na tabela. Por padro do aplicativo, o primeiro campo criado j vem com chave primria; como estamos criando o primeiro campo da tabela Clientes (ClientesID), mantenha essa sugesto do programa. Para validar as informaes inseridas, clique no boto Apply Changes (aplicar alteraes), destacado em vermelho, abaixo.

O MySQL Administrator ainda pedir sua confirmao sobre a criao da tabela, apresentando as configuraes da mesma no formato SQL numa nova janela, como se observa abaixo. Confirme clicando em Execute.

Finalizada esta seqncia a tabela estar criada, como se v na prxima figura. Siga o mesmo procedimento para a criao das tabelas Titulos, CD e Pedidos. Observao: desmarque a opo de auto-incremento das chaves primrias das tabelas Titulos e CD.

38

Uma vez criadas todas as tabelas, precisamos agora ajustar alguns campos que funcionaro como chave estrangeira, relacionando duas ou mais tabelas entre si. Para a criao de chaves estrangeiras (caso das tabelas CD e Pedidos), siga este procedimento: 1. Edite a tabela em que deseja inserir uma chave estrangeira, neste exemplo usaremos a tabela CD, que tem como chave estrangeira o campo TituloID. Selecione na caixa de edio a aba Foreign Keys, e pressione o sinal de +, logo abaixo da caixa de rea de texto, esquerda, como indicado na figura abaixo.

2. Surgir uma pequena janela pedindo que informe o nome do campo que servir de chave estrangeira, como indicado abaixo. Digite o nome do campo TituloID, que j foi criado nesta tabela; em seguida confirme pressionando o boto OK. 39

3. O campo TituloID passa a constar da caixa de rea de texto. Agora, selecione a tabela Titulos na caixa de texto Ref. Table, que far o vnculo com esta tabela atravs do campo de mesmo nome. Observe que na tabela abaixo da caixa Ref. Table surgem os nomes dos campos vinculados de ambas as tabelas, indicando a criao da chave estrangeira, como se observa na figura abaixo.

4. Selecione a opo Cascade para ambas as caixas de texto: On Delete e On Update, como destacado na figura acima. Aplique as mudanas efetuadas na tabela CD clicando sobre o boto Apply Changes e siga o mesmo procedimento para a criao das chaves estrangeiras na tabela Pedidos. A criao das tabelas est pronta; resta-nos agora popular estas tabelas, ou seja, inserir dados nos diversos campos de cada tabela criada. Para isso, utilizaremos a ferramenta MySQL Query Browser, uma interface grfica amigvel que facilitar a insero dos dados nas tabelas. Ao fazermos a chamada ferramenta, uma caixa de dilogo surge, pedindo o nome da base de dados que ser utilizada, como se observa na figura abaixo. Informe o nome da base de dados e pressione OK para entrar no MySQL Query Browser.

40

A janela que se abre est indicada abaixo, exibindo direita todas as tabelas criadas na base de dados deste exerccio, bem como todas as bases de dados existentes no MySQL.

Para popular a tabela Clientes com vrios scripts SQL de uma nica vez, clique no item de menu Arquivo e selecione a opo New Script Tab. Surgir uma tela de script denominada Script 1, como indicado na figura abaixo.

41

Copie e cole nessa rea os comandos de insero de dados a seguir:


Insert into Clientes values (1,'Mike Barott','1756 7th St','(325)200-2378'); Insert into Clientes values (2,'Catherine Brannen','7927 Ave H','(218)354-1091'); Insert into Clientes values (3,'David Carroll','491 18th St','(563)668-4177'); Insert into Clientes values (4,'Donna Courville','7764 Ave K','(562)513-8534'); Insert into Clientes values (5,'Jack Dodd','4627 11th St','(779)601-7769'); Insert into Clientes values (6,'Joe Ferguson','3060 Ave K','(515)801-1337'); Insert into Clientes values (7,'Marvin Gilmer','7394 12th St','(371)439-3652'); Insert into Clientes values (8,'Matthew Hand','1756 18th St','(600)591-2392'); Insert into Clientes values (9,'Antonio Holder','8691 Ave I','(172)408-3976'); Insert into Clientes values (10,'John Johnson','1334 Ave J','(473)366-5094'); Insert into Clientes values (11,'Pam Kwon','4508 15th St','(292)166-5268'); Insert into Clientes values (12,'Manuel Machac','764 Ave U','(552)693-9213'); Insert into Clientes values (13,'Basil McMeans','7464 12th St','(745)195-8065'); Insert into Clientes values (14,'Dana Murphy','3934 10th St','(715)121-8090'); Insert into Clientes values (15,'Aubrey Patterson','7567 Ave Z','(230)325-6709'); Insert into Clientes values (16,'Loyd Ramsower','1230 18th St','(697)307-9647'); Insert into Clientes values (17,'Brenda Rowland','1067 21th St','(657)578-1850'); Insert into Clientes values (18,'James Simmons','5816 Ave W','(136)907-5726'); Insert into Clientes values (19,'Lydia Stratton','546 16th St','(304)589-2216'); Insert into Clientes values (20,'Sue Turman','1341 Ave A','(695)123-9553');

Uma vez colados os comandos SQL na rea de scripts do MySQL Query, Browser, clique no boto Execute, destacado em vermelho na figura acima, para inserir os dados. Siga o mesmo procedimento para popular a tabela Titulos (apague os comandos anteriores antes de inserir estes):
Insert into Titulos values (1,'The Perfect Storm',2000,1.50); Insert into Titulos values (42,'Fantasia',2000,0.40); Insert into Titulos values (2,'Mission Impossible 2',2000,2.10); Insert into Titulos values (4,'Terminator 2: Judgement Day',1991,2.80); Insert into Titulos values (5,'The Patriot',2000,1.96); Insert into Titulos values (6,'Any Given Sunday',1999,1.75); Insert into Titulos values (7,'American Psycho',2000,1.89); Insert into Titulos values (8,'American Beauty',1999,1.62); Insert into Titulos values (9,'U-571',2000,1.89); Insert into Titulos values (10,'Leon - The Professional',1994,2.10); Insert into Titulos values (11,'The Sound of Music',1965,2.10); Insert into Titulos values (13,'Magnolia',2000,2.10); Insert into Titulos values (14,'High Fidelity',2000,2.20); Insert into Titulos values (15,'The Princess Bride',1987,1.40); Insert into Titulos values (16,'Toy Story 2',1995,2.80); Insert into Titulos values (17,'The Little Mermaid 2',2000,2.10); Insert into Titulos values (18,'Edward Scissorhands',1990,2.10); Insert into Titulos values (19,'North by Northwest',1959,1.75); Insert into Titulos values (20,'The Matrix',1999,1.75); Insert into Titulos values (21,'Erin Brockovich',2000,1.89); Insert into Titulos values (22,'Jurassic Park : Lost World',1993,3.78); Insert into Titulos values (23,'Pitch Black',2000,1.89); Insert into Titulos values (24,'Braveheart',1995,2.10); Insert into Titulos values (25,'Saving Private Ryan',1999,2.45); Insert into Titulos values (26,'The Shawshank Redemption',1994,1.40); Insert into Titulos values (27,'Shanghai Noon',2000,2.10);

42

Insert into Titulos values (28,'28 Days',2000,1.75); Insert into Titulos values (29,'Independence Day',1996,2.45); Insert into Titulos values (30,'The Sopranos',1999,7.00); Insert into Titulos values (31,'Fargo',1996,1.40); Insert into Titulos values (32,'The Green Mile',1999,1.75); Insert into Titulos values (34,'Final Destination',2000,1.75); Insert into Titulos values (35,'Titan A. E.',2000,1.89); Insert into Titulos values (36,'Mission to Mars',2000,2.10); Insert into Titulos values (37,'Frequency',2000,1.75); Insert into Titulos values (38,'The Nightmare Before Christmas',1993,2.10); Insert into Titulos values (39,'The Rocky Horror Picture Show',1975,2.10); Insert into Titulos values (40,'Chicken Run',2000,1.89); Insert into Titulos values (41,'Gladiator',2000,1.80); Insert into Titulos values (3,'Men in Black',1997,2.40); Insert into Titulos values (12,'This is Spinal Tap',1984,1.89); Insert into Titulos values (33,'The Bridge over the River Kwai',1957,1.75);

Siga o mesmo procedimento para popular a tabela CD, inserindo no Script 1 os comandos abaixo:
Insert into CD values (12345,1,'DVD'); Insert into CD values (12352,42,'DVD'); Insert into CD values (12357,2,'DVD'); Insert into CD values (12364,4,'VHS'); Insert into CD values (12378,5,'DVD'); Insert into CD values (12389,6,'VHS'); Insert into CD values (12400,7,'VHS'); Insert into CD values (12405,8,'DVD'); Insert into CD values (12414,9,'DVD'); Insert into CD values (12426,10,'DVD'); Insert into CD values (12437,11,'DVD'); Insert into CD values (12446,13,'VHS'); Insert into CD values (12453,14,'DVD'); Insert into CD values (12465,15,'VHS'); Insert into CD values (12479,16,'DVD'); Insert into CD values (12487,17,'VHS'); Insert into CD values (12492,18,'DVD'); Insert into CD values (12498,19,'VHS'); Insert into CD values (12506,20,'DVD'); Insert into CD values (12513,21,'VHS'); Insert into CD values (12514,21,'DVD'); Insert into CD values (12526,21,'DVD'); Insert into CD values (12527,22,'DVD'); Insert into CD values (12528,22,'VHS'); Insert into CD values (12535,23,'DVD'); Insert into CD values (12544,24,'VHS'); Insert into CD values (12550,25,'VHS'); Insert into CD values (12557,26,'DVD'); Insert into CD values (12558,26,'DVD'); Insert into CD values (12568,27,'VHS'); Insert into CD values (12577,28,'VHS'); Insert into CD values (12583,29,'VHS'); Insert into CD values (12592,30,'VHS'); Insert into CD values (12603,31,'VHS'); Insert into CD values (12612,32,'DVD');

43

Insert into CD values (12613,32,'VHS'); Insert into CD values (12626,34,'VHS'); Insert into CD values (12639,35,'VHS'); Insert into CD values (12650,36,'DVD'); Insert into CD values (12655,37,'VHS'); Insert into CD values (12667,38,'DVD'); Insert into CD values (12674,39,'DVD'); Insert into CD values (12679,40,'VHS'); Insert into CD values (12691,41,'DVD'); Insert into CD values (12700,3,'VHS'); Insert into CD values (12713,12,'DVD'); Insert into CD values (12716,33,'VHS'); Insert into CD values (12725,1,'VHS'); Insert into CD values (12726,40,'VHS'); Insert into CD values (12727,6,'VHS'); Insert into CD values (12728,30,'VHS'); Insert into CD values (12736,15,'VHS'); Insert into CD values (12743,33,'VHS');

Finalmente, para a tabela Pedidos, insira no Script 1 os comandos abaixo:


Insert into Pedidos values (1,1,12345,date'2009-08-05','I'); Insert into Pedidos values (2,1,12352,date'2009-08-05','I'); Insert into Pedidos values (3,2,12364,date'2009-08-07','I'); Insert into Pedidos values (4,3,12674,date'2009-08-08','I'); Insert into Pedidos values (5,4,12550,date'2009-08-09','I'); Insert into Pedidos values (6,5,12592,date'2009-08-09','I'); Insert into Pedidos values (7,6,12639,date'2009-08-09','I'); Insert into Pedidos values (8,7,12716,date'2009-08-12','I'); Insert into Pedidos values (9,8,12713,date'2009-08-12','I'); Insert into Pedidos values (10,9,12437,date'2009-08-13','I'); Insert into Pedidos values (11,10,12655,date'2009-08-14','I'); Insert into Pedidos values (12,10,12716,date'2009-08-14','I'); Insert into Pedidos values (13,11,12389,date'2009-08-15','I'); Insert into Pedidos values (14,14,12352,date'2009-08-16','I'); Insert into Pedidos values (15,16,12400,date'2009-08-17','I'); Insert into Pedidos values (16,17,12479,date'2009-08-17','I'); Insert into Pedidos values (17,18,12453,date'2009-08-18','I'); Insert into Pedidos values (18,19,12592,date'2009-08-19','I'); Insert into Pedidos values (19,20,12713,date'2009-08-20','I');

Mdulo 6 Manipulao de dados com linguagem SQL


Princpios das aplicaes JDBC
Uma aplicao que necessite acessar um banco de dados deve utilizar vrias classes e interfaces da API JDBC para realizar as tarefas desejadas. A figura abaixo apresenta os principais elementos do JDBC, destacando as classes, as interfaces e os mtodos mais usados. A execuo de praticamente todas as operaes possveis pode provocar o lanamento da exceo java.sql.SQLException, tornando obrigatrio o seu tratamento.

44

DriverManager getConnection()

DataSource getConnection()

Statement executeUpdate() getResultSet() executeQuery()

Connection createStatement() prepareCall() prepareStatement() PreparedStatement set...() CallableStatement set...() execute() get...() executeUpdate() execute() getResultSet() executeQuery() ResultSet get...() next() set...()

Conexo
Considerando que o driver necessrio para carregar o banco de dados encontra-se carregado, utilizada uma das verses do mtodo getConnection da classe DriverManager para obter-se uma conexo com o banco, tal como: Connection connection = DriverManager.getConnection(url, usuario, senha); Uma aplicao pode possuir uma ou mais conexes com o mesmo ou com diferentes bancos de dados. Connection , portanto, uma interface que representa uma sesso entre uma aplicao e um banco de dados. Abaixo, alguns de seus mtodos: void close(): fecha a conexo com o banco de dados, liberando os recursos utilizados. void commit(): torna permanentes as alteraes realizadas desde o ltimo commit, ou rollback. Statement createStatement(): cria objeto para envio de comandos SQL estticos ao banco de dados, opcionalmente com os tipos de navegao e concorrncia indicados. boolean getAutoCommit(): verifica se o banco de dados est ou no est em modo auto-commit. DatabaseMetaData getMetData(): obtm informaes sobre o banco de dados e a conexo em uso. boolean isReadOnly(): verifica se o banco de dados est ou no est em modo somente leitura. CallableStatement prepareCall(String sql): cria objeto apropriado para chamada de procedimentos armazenados. PreparedStatement prepareStatement(String sql): cria objeto para envio de comandos SQL parametrizados ao banco de dados, opcionalmente com os tipos de navegao e concorrncia indicados. 45

void rollback(): cancela as alteraes efetuadas desde o ltimo commit ou rollback realizado. void setAutoCommit(boolean estado): ajusta o estado de auto-commit do banco de dados. void setReadOnly(boolean estado): ajusta o estado de leitura exclusiva do banco de dados.

Como padro, uma conexo estabelecida em modo auto-commit, que consolida as alteraes realizadas a cada operao. Uma vez que a conexo for estabelecida com sucesso, as operaes sobre os dados ou sobre a estrutura do banco de dados podero ser realizadas de quatro maneiras diferentes: interativa, em lote, preparada (otimizada) ou acionamento de stored procedures (procedimentos armazenados). Se o modo de operao for ajustado para transacional com setAutoCommit(false), as operaes que provocam alteraes devero ser confirmadas por meio de chamadas ao mtodo commit() ou canceladas com rollback().

Operao interativa
A operao interativa se faz por meio da interface java.sql.Statement, a qual permite o envio de comandos SQL estticos, isto , no parametrizados, para o banco de dados e o retorno dos resultados obtidos. Por meio do mtodo createStatement(), disponvel na interface Connection, possvel obter um objeto que representa esta interface, como segue: Statement statement = connection.createStatement(); O padro dos objetos Statement criados TYPE_FORWARD_ONLY e CONCUR_READ_ONLY, que possibilita apenas navegao frente nos resultados obtidos, com leitura concorrente dos registros. Abaixo, alguns mtodos da interface Statement: void addBatch(String): adiciona o comando dado lista de comandos corrente. void cancel(): cancela a operao SQL em andamento, se o cancelamento for suportado pelo driver e pelo banco de dados. void clearBatch(): elimina todos os comandos da lista de comandos corrente. void close(): libera todos os recursos utilizados por este objeto. boolean execute(String sql): executa o comando SQL dado, indicando se existe o retorno de resultados. int[] executeBatch(): submete a lista de comandos para execuo. ResultSet executeQuery(String sql): executa o comando SELECT dado,

retornando um objeto ResultSet. int executeUpdate(String sql): executa o comando SQL dado, retornando o nmero de linhas afetadas;

46

boolean getMoreResults(): indica se existem mais objetos ResultSet retornados pela ltima operao realizada por este Statement.

ResultSet

getResultSet(): retorna o objeto ResultSet correspondente aos

resultados obtidos.

Operao em lote
Ainda utilizando objetos do tipo Statement, possvel definir uma lista ou lote de comandos (batch), o qual ser enviado e executado de uma vez pelo banco de dados, acelerando o processamento de tarefas mais complexas. Neste caso, emprega-se o mtodo addBatch(String) para adicionar um comando lista corrente. Quando o lote de comandos estiver pronto, sua execuo pode ser solicitada por meio de executeBatch(), que retorna um array de valores inteiros correspondentes ao nmero de linhas afetadas por cada comando do lote. Finalmente, os comandos do lote podem ser descartados com clearBatch(), o que permite reutilizar o objeto Statement para o preparo e para a execuo de outro lote de comandos.

Stored Procedure (operao preparada)


Um objeto do tipo PreparedStatement permite definir um comando SQL que ser prcompilado no banco de dados, permitindo sua execuo eficiente. O comando SQL preparado pode conter um ou mais parmetros de entrada representados pelo smbolo de interrogao (?), que conhecido como marcador de parmetro. Os parmetros de entrada devem ser fornecidos antes de cada execuo do comando SQL preparado.

O componente JTable
O JTable o componente da famlia Swing destinado a exibio tabular de dados. Como todo componente Swing, as responsabilidades de apresentao dos dados e interface com o usurio ficam a cargo do prprio JTable, enquanto as demais, relacionadas ao armazenamento e obteno dos dados exibidos so encontradas em modelos especficos de dados. Isso permite que a representao interna dos dados e a sua forma de obteno sejam mantidas separadas das tarefas de apresentao. A seguir, um resumo das principais caractersticas deste componente: AUTO_RESIZE_ALL_COLUMNS ...: constantes para redimensionamento da tabela. JTable(TableModel tm): constri uma tabela para exibir o contedo e os nomes de colunas, usando o modelo dado. void clearSelection(): retira a seleo corrente. int columnAtPoint(Point p), int rowAtPoint(Point p): retorna o ndice da coluna ou linha sob o ponto dado.

47

boolean editCellAt(int linha, int coluna): inicia a edio da clula indicada por (linha, coluna), se possvel. TableCellEditor getCellEditor(int linha, int coluna): retorna o editor de clula apropriado para a clula especificada. Class<?> getColumnClass(int coluna): retorna a classe dos elementos da coluna indicada. int getColumnCount(), int getRowCount(): retorna o nmero de colunas ou linhas da tabela. int getEditionColumn(), getEditionRow(): obtm o nmero da coluna ou linha em edio.

Color

getGridColor(),

getSelectionBackground(),

getSelectionForeground():

retorna, respectivamente, as cores usadas para o desenho da grade, do fundo e do primeiro plano das selees. TableModel getModel(): obtm o modelo de dados da tabela. int getSelectedColumn(), getSelectedRow(): obtm o ndice da coluna e da linha selecionada. Object getValueAt(int linha, int coluna): retorna o contedo da clula dado por (linha, coluna). boolean isCellEditable(int linha, int coluna), isCellSelected(int linha, int coluna): determina se a clula ou no editvel ou se est ou no selecionada. boolean isEditing(): retorna se existe ou no alguma clula em edio. boolean isShowGrid(): retorna se a grade exibida ou no.

Modelo de dados para JTable


Pra que seja possvel maior controle sobre o contedo e as caractersticas de um JTable, sugere-se a construo de um modelo de dados prprio. Isto pode ser feito estendendo a classe javax.swing.table.AbstractTableModel, que define as funcionalidades padronizadas de um modelo de dados para tabelas, definidas pela interface javax.swing.table.TableModel. Abaixo, algumas caractersticas da interface TableModel, que especifica como um JTable acessar seu modelo de dados: void addTableModelListener(TableModelListener tml): adiciona um observador que ser notificado com as mudanas ocorridas com o modelo de dados. int getColumnCount(): retorna a quantidade de colunas ao modelo de dados. String getColumnName(int coluna): retorna o nome da coluna indicada. int getRowCount(): retorna a quantidade de linhas do modelo de dados. 48

Object getValueAt(int linha, int coluna): retorna o objeto contido na linha e na coluna do modelo de dados. void setValueAt(Object o, int linha, int coluna): ajusta com contedo a clula indicada com o objeto fornecido.

Exerccios de Laboratrio do mdulo 6


1. Criar uma classe Java para facilitar a utilizao de um banco de dados qualquer. A conexo com um banco de dados por meio da JDBC emprega algum cdigo repetitivo, assim uma classe de conexo com mtodos para estabelecer e para encerrar a conexo com um banco de dados facilita o trabalho do programador. A classe deve seguir o padro de projeto Singleton. Singleton trata da criao de objetos; atravs dele, garantimos a existncia de uma nica instncia de uma classe, mantendo um nico ponto de acesso dentro do sistema. E qual a utilidade disso? Simples: objetos responsveis pela utilizao racional das conexes feitas a um banco de dados, ou pelo gerenciamento dos documentos a serem impressos em uma impressora, entre outras aplicaes, no devem ser instanciados mais de uma vez. Imagine o problema que seria criar duas instncias em uma aplicao que lidam com uma mesma impressora ao mesmo tempo: isso geraria inmeros problemas. Para prevenir que uma classe seja instanciada mais de uma vez, criamos um construtor privado dentro da classe. Dessa forma, a classe s pode ser instanciada dentro de algum de seus prprios mtodos. Uma vez que s podemos instanciar a classe dentro de um mtodo, temos que fazer com que esse mtodo nos garanta que apenas um objeto seja criado. Para isso, criaremos uma varivel esttica que guardar o nico objeto criado. Caso a varivel esteja nula, o mtodo instanciar a classe e retornar o objeto ao usurio. Caso haja uma instncia, o mtodo apenas retorna o objeto existente. Abaixo a listagem da classe ConectaBD, utilizando o padro de projeto Singleton:
package br.unip.cc4si4.ALPOO; import java.sql.*; public class ConectaBD { //Varivel esttica que guardar a instncia da classe ConectaBD. private static ConectaBD instancia = null; //Variavel para conexao base de dados. private Connection conexao = null; //Varivel para determinao da quantidade de clientes conectados base. private int quantidadeDeConexoes = 0; //Construtor privado private ConectaBD(){ try{ //Propriedades da conexo base de dados: //Especifica o driver JDBC utilizado. String bdDriver = "com.mysql.jdbc.Driver"; //Cria a url de acesso ao banco MySQL fornecendo: //o driver jdbc, o nome banco, o endereo (localhost //neste caso) com a porta de acesso e a base de //dados criada na aula passada. String bdUrl = "jdbc:mysql://localhost:3306/alpoo"; //Define o usurio de acesso ao banco de dados. String bdUsuario = "root"; //Define a senha de acesso ao banco de dados. String bdSenha = ""; //Carregamento dinmico do driver por meio do mtodo //forName(String) da classe Class. Class.forName(bdDriver); //Acesso base de dados com usurio e senha.

49

if(bdUsuario.length() != 0) conexao = DriverManager.getConnection(bdUrl, bdUsuario, bdSenha); //Acesso direto base de dados (sem usurio e senha). else conexao = DriverManager.getConnection(bdUrl); System.out.println("BD[Conexao OK]"); } //Caso haja algum problema com o driver utilizado, //ser gerada uma exceo. catch(ClassNotFoundException cnfe){ System.out.println("Driver JDBC nao encontrado!"); } //Caso haja algum problema com o comando SQL, //ser gerada uma exceo. catch(SQLException sqle){ System.out.println("Problemas na conexao com a base de dados!"); } } //Mtodo esttico que retorna uma instncia unica //da classe ConectaBD. Padro Singleton. public static ConectaBD getInstancia(){ if(instancia == null) instancia = new ConectaBD(); return instancia; } //Mtodo para retornar a conexo disponvel, //contabilizando a quantidade de clientes //acessando a base de dados. public Connection getConexao(){ if(conexao == null) throw new RuntimeException("conexao == null"); quantidadeDeConexoes++; System.out.println("BD[Cliente conectado]"); return conexao; } //Mtodo que decrementa o nmero de clientes //conectados base, efetuando o encerramento //da conexo quando no restarem mais clientes. public void encerraConexao(){ System.out.println("BD[Cliente desconectado]"); quantidadeDeConexoes--; if(quantidadeDeConexoes > 0) return; try{ conexao.close(); instancia = null; System.out.println("BD[Conexao encerrada]"); conexao = null; } catch(SQLException sqle){ System.out.println("Problemas ao desconectar com a base de dados!"); } } }

2. A consulta aos dados de uma tabela em um banco de dados e sua exibio em um componente JTable uma estratgia elegante e conveniente para a construo de aplicaes, mas exige a adaptao do modelo de dados da tabela para possibilitar tal operao via JDBC. A classe ModeloDeTabela, cuja listagem segue abaixo, capaz de obter seu contedo de um banco de dados conforme uma consulta (query) especificada.
package br.unip.cc4si4.ALPOO; import java.sql.*; import java.util.ArrayList; import javax.swing.table.AbstractTableModel; public class ModeloDeTabela extends AbstractTableModel { //Atributos da classe ModeloDeTabela. private ArrayList<Object[]> linhas; private String[] colunas; private Statement comando; private String consulta; //Construtor da classe. public ModeloDeTabela(String consulta){ try{ //Tenta efetuar uma conexo ao banco de dados. comando = ConectaBD.getInstancia().getConexao().createStatement();

50

//Se a conexo teve xito, leia a consulta SQL desejada. this.consulta = consulta; //Instancia o atributo linhas, que receber um array de objetos //que o resultado obtido na consulta SQL enviada ao banco. linhas = new ArrayList<Object[]>(); //Chama o mtodo carregaDados, responsvel pela estruturao dos //dados obtidos na consulta SQL enviada ao banco de dados. carregaDados(); //Se houve algum problema na conexo ao banco de dados, exibe erro. }catch(Exception e){ System.out.println("Modelo de Dados["+e.toString()+"]"); } } //Mtodo que far o carregamento dos dados. public void carregaDados(){ System.out.println("Modelo de Dados[carregaDados()]"); try{ //Tenta ler a massa de dados obtida apos a execuo //da consulta SQL ao banco de dados. ResultSet resultado = comando.executeQuery(consulta); //Obtm o nmero, tipo e propriedades da massa de dados. ResultSetMetaData rsmd = resultado.getMetaData(); //Obtm a quantidade de colunas da massa de dados. int numeroDeColunas = rsmd.getColumnCount(); //Instancia o atributo colunas. colunas = new String[numeroDeColunas]; //Para a quantidade de colunas obtida na massa de dados, //obtenha o nome de cada coluna. for(int i=1; i<numeroDeColunas; i++) colunas[i] = rsmd.getColumnName(i); //Apague o contedo do atributo linhas, haja algo ou no. linhas.clear(); //Enquanto houver linhas no lidas na massa de dados... while(resultado.next()){ //...crie um objeto linha, do tipo array, com a mesma //quantidade de colunas obtida na massa de dados. Object linha[] = new Object[numeroDeColunas]; //Para cada coluna lida... for(int i=0; i<numeroDeColunas; i++) //...armazene o seu contedo na posio i da linha. linha[i] = resultado.getObject(i+1); //E adicione essa linha ao atributo privado linhas, //que quem armazena todas as linhas obtidas, ou seja, //toda a massa de dados da consulta. linhas.add(linha); } //Encerra a leitura da massa de dados. resultado.close(); //Atualiza os dados exibidos na JTable fireTableDataChanged(); //Se houve algum problema na leitura dos dados, exibe erro. }catch(Exception e){ System.out.println("Modelo de Dados["+e.toString()+"]"); } } //Mtodos de implementao obrigatria //da interface AbstractTableModel: //Obtm a quantidade de colunas. public int getColumnCount(){ return colunas.length; } //Obtm a quantidade de linhas. public int getRowCount(){ return linhas.size(); } //Obtm o contedo de uma clula (coluna x linha). public Object getValueAt(int linha, int coluna){ try{ Object celula[] = linhas.get(linha); return celula[coluna]; }catch(Exception e){ System.out.println("Modelo de Dados["+e.toString()+"]"); } return null; } }

3. Construir uma aplicao que componha um frame contendo um JPanel e este um JTable, o qual exibe os dados da tabela Clientes por meio de uma consulta SQL. O modelo de dados do 51

JTable j foi montado no exerccio 2. A consulta e o ttulo da janela so fornecidos na prpria classe. A conexo com o banco de dados fica a cargo da classe ConectaBD, feita no exerccio 1. A deteco de eventos fica por conta de uma classe observadora especfica para isso. Abaixo a listagem da classe JanelaExibeDados:
package br.unip.cc4si4.ALPOO; import java.awt.*; import javax.swing.*; public class JanelaExibeDados extends JFrame { //Construtor public JanelaExibeDados(){ //Cria e insere um objeto PainelExibeClientes. PainelExibeClientes pec = new PainelExibeClientes(); this.getContentPane().add(pec, BorderLayout.CENTER); //Instancia o observador deste frame. ObservadorDoPainelExibeClientes odpec = new ObservadorDoPainelExibeClientes(this); this.addWindowListener(odpec); //Fecha o frame. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); } //Mtodo para encerrar a conexo com o banco de dados. public void encerrarConexao(){ ConectaBD.getInstancia().encerraConexao(); } //Mtodo executvel. public static void main(String[] args){ JanelaExibeDados jed = new JanelaExibeDados(); jed.setTitle("Clientes"); jed.setVisible(true); } }

A seguir, a listagem da classe que compe o painel, PainelExibeClientes:


package br.unip.cc4si4.ALPOO; import java.awt.*; import javax.swing.*; public class PainelExibeClientes extends JPanel { //Atributos da classe. private JTable tabela; private ModeloDeTabela modelo; private JButton botaoatualiza; //Construtor public PainelExibeClientes(){ //Seleciona gerenciador de leiaute. BorderLayout borderlayout = new BorderLayout(); this.setLayout(borderlayout); //Requisitos da consulta. String consulta = null; consulta = "select clienteid, clientenome, clienteendereco, " + "clientetelefone from clientes"; //Cria um objeto modelo de dados. modelo = new ModeloDeTabela(consulta); //E utiliza este modelo para criar um JTable. tabela = new JTable(modelo); //Cria e insere um painel rolante ao painel. JScrollPane sp = new JScrollPane(tabela); this.add(sp, BorderLayout.CENTER); //Cria e insere um botao ao painel. botaoatualiza = new JButton("Atualizar"); botaoatualiza.setSize(5, 2); this.add(botaoatualiza, BorderLayout.SOUTH); //Instancia o observador deste painel. ObservadorDoPainelExibeClientes odpec = new ObservadorDoPainelExibeClientes(this); //Gera evento para atualizacao dos dados da tabela. botaoatualiza.addActionListener(odpec); } //Mtodo para carregar a tabela Clientes. public void carregarClientes(){ modelo.carregaDados(); } }

E a listagem da classe de observao de eventos, ObservadorDoPainelExibeClientes: 52

package br.unip.cc4si4.ALPOO; import java.awt.event.ActionListener; import java.awt.event.WindowListener; import java.awt.event.ActionEvent; import java.awt.event.WindowEvent; public class ObservadorDoPainelExibeClientes implements ActionListener, WindowListener { //Atributos privados. private PainelExibeClientes pec; private JanelaExibeDados jed; //Construtores, um para o painel, outro para o frame. public ObservadorDoPainelExibeClientes(PainelExibeClientes painel){ pec = painel; } public ObservadorDoPainelExibeClientes(JanelaExibeDados janela){ jed = janela; } //Este mtodo chamado pelo sistema em tempo de execuo. //Voc deve adicionar o cdigo a ser executado //em resposta carga da tabela no painel. public void actionPerformed(ActionEvent evento){ //Incio do seu cdigo: pec.carregarClientes(); } //Este mtodo chamado pelo sistema em tempo de execuo. //Voc deve adicionar o cdigo a ser executado //em resposta ao fechamento do frame. public void windowClosing(WindowEvent e){ //Incio do seu cdigo: jed.encerrarConexao(); } //Mtodos de implementao obrigatria, so necessrios //para que a classe no gere erros e compile corretamente, //mas no sero utilizados para este exemplo. public void windowDeiconified(WindowEvent e){ System.out.println(e.toString()); } public void windowIconified(WindowEvent e){ System.out.println(e.toString()); } public void windowActivated(WindowEvent e){ System.out.println(e.toString()); } public void windowDeactivated(WindowEvent e){ System.out.println(e.toString()); } public void windowClosed(WindowEvent e){ System.out.println(e.toString()); } public void windowOpened(WindowEvent e){ System.out.println(e.toString()); } }

4. Desafio: construir uma aplicao contendo um frame e, dentro deste, quatro painis, um para cada uma das quatro tabelas criadas, mas agora os dados devem ser exibidos em caixas de texto e deve haver dois botes dentro de cada painel: um para avanar e outro para retroceder na massa de dados obtida. Montar no frame uma barra de menu que controle o painel a ser exibido.

Mdulo 7 MVC: Model View Controller


O padro de projeto Modelo-Viso-Controlador foi inventado para a linguagem Smalltalk com o objetivo de desacoplar a interface grfica de uma aplicao do cdigo que realmente executa o trabalho. Este padro se tornou to importante que afetou completamente o cdigo no qual o Smalltalk foi construdo, sendo aplicvel tambm a outras linguagens orientadas a objeto.

53

O Modelo
No MVC o Modelo o cdigo que realiza alguma tarefa. Ele estruturado sem necessariamente haver uma preocupao sobre como ele se parece e se sente quando apresentado ao usurio. Possui uma interface puramente funcional, o que significa que contm um conjunto de funes pblicas que podem ser utilizadas para alcanar toda a sua funcionalidade. Algumas dessas funes so mtodos de consulta que permitem a um usurio obter informao sobre o estado atual do modelo. Entretanto, um modelo tem que estar apto a registrar vises e tem que estar apto a notificar todas as suas vises registradas quando qualquer uma de suas funes fora uma mudana em seu estado. Em Java, um Modelo consiste de uma ou mais classes que extendem a classe java.util.Observable (observado). Esta superclasse fornecer toda a infraestrutura de registro / notificao necessria para suportar um conjunto de vises.

Muitas Vises
Um modelo em MVC pode conter diversas vises. Dois exemplos seriam: a viso de linhas e colunas de uma planilha e a viso de um grfico de pizza de alguma coluna dessa mesma planilha. Uma viso fornece componentes GUI para um modelo. Quando um usurio manipula a viso de um modelo, essa viso informa um controlador da mudana desejada pelo usurio. Em Java, as vises so construdas com componentes AWT ou Swing. Entretanto, as vises tm que representar a interface java.util.Observer (observador).

Muitos controladores
As vises em MVC esto associadas a controladores que atualizam o model sempre que necessrio, medida que um usurio interage com a viso associada. Obviamente, o modelo notificar todas as vises registradas que uma mudana ocorreu e ento elas atualizaro aquilo que elas exibem ao usurio da maneira apropriada. Em Java, os controladores so os observadores da estrutura de eventos da linguagem.

Como tudo isso funciona


Primeiro voc escreve um modelo que extenda a classe java.util.Observable. Voc fornece seus mtodos acessores (getX()) de classe para obterem informao acerca de seu estado atual e codifica seus mtodos modificadores (setX()) para atualizar o estado. Cada mtodo modificador deve chamar um mtodo do tipo setChanged() e um ou outro mtodo notifyObservers() depois que ele realmente alterou o estado. Os mtodos notifyObservers() enviaro uma mensagem de atualizao a cada observador registrado (viso). Existem verses desse mtodo que permitem que voc fornea informao adicional sobre a mudana. Depois voc pode criar uma ou mais vises. Cada viso deve representar a interface java.util.Observer e portanto codificar o mtodo de atualizao. O objeto no segundo 54

parmetro do mtodo ser usado para receber informao adicional, se fornecida, como se observa a seguir:
interface Observer{ void update(Observable t, Object o); }

A viso deve representar o mtodo de atualizao consultando o modelo (na verdade, o Observable t) para as mudanas que ele necessita e depois efetuar ela prpria as alteraes apropriadas. A viso tambm precisa se registrar junto ao modelo que ela deseja observar, enviando-lhe a mensagem addObserver. O modelo notificar todas as vises registradas, de modo que ele possa atualiz-las posteriormente. O motivo para que um modelo extenda a classe java.util.Observable que esta classe fornece toda a infraestrutura necessria para registrar e notificar um modelo, portanto voc no ter que codificar nada disso e pode se concentrar na funcionalidade de sua aplicao. Um modelo pode ter diversas vises. O MVC foi criado especificamente para permitir isso. Tambm, uma viso pode se registrar em diversos modelos e obter atualizaes de cada um. No preciso construir seu modelo de modo que ele seja um nico Observable (observado). Ao contrrio, diversas partes do modelo podem ser Observable separadamente, cada parte com seus prprios Observers (observadores).

Exerccios de Laboratrio do mdulo 7


1. Neste exerccio temos um modelo que realmente uma classe muito simples de ser codificada. Ela encapsula a idia de uma temperatura em graus Celsius e em Farenheit. Queremos obter dessa classe uma temperatura em ambas as unidades de medida de temperatura bem como alterar a temperatura nessas mesmas unidades de medida. Observe ainda que no existem elementos grficos aqui, mas temos alguma infraestrutura, nomeadamente as chamadas setChanged() e notifyObservers() nos mtodos modificadores. Abaixo a listagem da classe ModeloDeTemperatura:
package br.unip.cc4si4.ALPOO; import java.util.Observable; public class ModeloDeTemperatura extends Observable { //Atributo privado da classe. private double temperaturaFarenheit = 32.0; //Mtodo para leitura da temperatura em Farenheit. public double getFarenheit(){ return temperaturaFarenheit; } //Mtodo para leitura da temperatura em Celsius //a partir da converso da temperatura em Farenheit. public double getCelsius(){ return (temperaturaFarenheit - 32.0)*5.0/9.0; } //Mtodo para mudar a temperatura em Farenheit. public void setFarenheit(double tempF){ //Determina a nova temperatura. temperaturaFarenheit = tempF; //Marca a instncia desta classe, que do tipo observada, //como tendo sido alterada. setChanged();

55

//Como a instncia desta classe foi alterada, //notifique todos os seus observadores. notifyObservers(); } //Mtodo para mudar a temperatura em Celsius //a partir da converso da temperatura em Farenheit. public void setCelsius(double tempC){ temperaturaFarenheit = tempC*5.0/9.0 + 32.0; setChanged(); notifyObservers(); } }

56

57

58