Você está na página 1de 114

Programao JAVA

1. Programao Visual Bsica


A Interface Grfica com o Usurio, tambm conhecido como GUI - Graphical User Interface, em Java, feita atravs de bibliotecas de classes, sendo que a primeira a surgir foi a AWT (Abstract Window Toolkit). A AWT surgiu j na verso 1.0, mas se tornou confivel a partir da verso 1.1. A maneira como as classes dessa biblioteca trabalham garante a criao dos elementos da interface de usurio seguindo o comportamento destinado s ferramentas GUI nativas de cada plataforma (Windows, Mac, Solaris, ...). Alguns exemplos destes elementos so: botes, listas, menus, componentes de textos, containers (janelas e barras de menus), caixas de dilogo para abrir ou salvar arquivos, alm de elementos para manipulao de imagens, fontes e cores. A portabilidade de plataforma funcionava bem em aplicaes simples, mas aplicaes que envolviam elementos mais complexos, como menus e barras de rolagem, por exemplo, apresentavam diferenas de comportamento conforme a plataforma. O que aconteceu foi que as aplicaes visuais feitas em Java no se pareciam, e nem tinham as mesmas funcionalidades, com as aplicaes convencionais de cada plataforma. A partir da verso 2 do Java, a JFC (Java Foundation Classes) apresentou novos recursos para a construo da GUI das aplicaes, o que melhorou muito os problemas de portabilidade. So eles:

Java 2D: novas funes para desenhos e grficos. Drag & Drop: clicar, arrastar, copiar e colar. Swing: biblioteca de classes extenso da AWT, onde so apresentados novos componentes de interface e o que conhecido por look and feel, que uma adaptao perfeita da GUI ao sistema operacional especfico de desenvolvimento.

bom salientar que o Swing no substitui o AWT, mas o kit de ferramentas GUI mais utilizado para desenvolvimento de aplicaes visuais. O AWT continua existindo, mantendo a mesma arquitetura criada para o Java verso 1.1. O Swing possui muito mais recursos, alm de garantir maior portabilidade e, em boa parte dos casos, mais fcil de usar. Isso no significa que ou se utiliza AWT ou se utiliza Swing, normalmente o que acontece que elementos das duas bibliotecas so utilizados conjuntamente nas aplicaes. Referente a criao das aplicaes, exitem muitas ferramentas que auxiliam na produo de interfaces de usurio grficas, mas no se comparam a ferramentas para plataformas especficas,

como Delphi e VisualBasic, que so voltadas exclusivamente para esse fim. Boa parte da elaborao da interface da aplicao tem que ser feita manualmente, o que exige bastante trabalho.

1.1 Frames
Na AWT, a janela de mais alto nvel de uma aplicao (no est contida dentro de nenhuma outra) denominada Frame. No Swing, existe uma verso chamada JFrame, que derivada/estendida da classe Frame, possuindo alguns poucos mtodos adicionais relacionados manipulao da disposio visual dos frames .Todos os outros mtodos so derivados da classe Frame. Um frame pode conter diversos outros componentes da GUI. Para se definir um frame bsico baseado em AWT, deve-se:

Importar o pacote java.awt.*. Estender a classe Frame. Ter um mtodo main() para criar o objeto a partir do operador new. Torn-lo visvel.

Assim, o cdigo a seguir resulta no frame apresentado na figura 1.1.


import java.awt.*; public class FrameUm extends Frame { public static void main (String[] args) { FrameUm fr = new FrameUm(); fr.setVisible(true); } }

Para torn-lo visvel, possvel utilizar fr.show(); no lugar de fr.setVisible(true);. Percebe-se que no possvel fech-lo utilizando o boto fechar. Por enquanto, ela deve ser encerrada forando a finalizao do processo (ex.: finalizar tarefa no Windows, ou terminar processo na ferramenta especfica de desenvolvimento).

Figura 1.1. Frame FrameUm

O frame criado no possui tamanho definido, nem ttulo ou posicionamento. Para personalizar o frame necessrio inserir um mtodo construtor com as instrues necessrias. Exemplo:
import java.awt.*; public class FrameDois extends Frame { public FrameDois() //construtor { setTitle("Frame Dois"); // ttulo do Frame setSize(300, 200); // largura: 300 pixels altura: 200 pixels setResizable(false); // no permite o redimensionamento

setLocation(200, 100); // x: 200 pixels } public static void main (String[] args) { FrameDois fr = new FrameDois(); fr.setVisible(true); } }

y: 100 pixels

A figura 1.2 mostra o resultado da execuo, um frame com largura 300 x 200 pixels (setSize()), com o ttulo Frame Dois (setTitle()), que no permite redimensionamento (setResizable()).

Figura 1.2. Frame FrameDois

Alm disso, o setLocation() realiza o posicionamento em tela do frame, seguindo o sistema de coordenadas do Java (figura 1.3), medidas em pixels, conforme a resoluo atual da tela. No exemplo, o frame fica posicionado em 200 pixels para x e 100 pixels para y.
(0 ,0) x

(x, y)

Figura 1.3. Sistema de coordenadas do Java

Conforme j mencionado, o frame ainda no pode ser fechado. Para que isso acontea necessrio ter uma maneira de se ter a notificao de quando ele fechado. A partir da manipulao desse evento, mostrado no exemplo a seguir, possvel fechar o frame. necessrio importar o pacote java.awt.event.* para manipular eventos do AWT. O modelo de eventos e os demais eventos de janela sero vistos em sees posteriores.
import java.awt.*;

import java.awt.event.*; public class FrameTres extends Frame { public FrameTres() //construtor { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Frame Trs"); // ttulo do Frame setSize(300, 200); // largura: 300 pixels altura: 200 pixels setResizable(false); // no permite o redimensionamento setLocation(200, 100); // x: 200 pixels y: 100 pixels } public static void main (String[] args) { FrameTres fr = new FrameTres(); fr.setVisible(true); } }

Ainda em relao ao posicionamento, dependendo da resoluo da tela onde o frame ser aberto, pode se ter situaes bem desagradveis, como, por exemplo, o frame ser aberto e ficar com parte fora da tela. necessrio ento posicionar o frame em coordenadas que independam da resoluo utilizada. O exemplo a seguir abrir um frame com a metade do tamanho da tela, posicionado no centro, respeitando a resoluo.
import java.awt.*; import java.awt.event.*; public class FrameQuatro extends Frame { public FrameQuatro() //construtor { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); Toolkit tk = Toolkit.getDefaultToolkit(); Dimension d = tk.getScreenSize(); setSize(d.width / 2, d.height / 2); setLocation(d.width / 4, d.height / 4); Image img = tk.getImage("icone.gif"); setIconImage(img); setTitle("Frame Quatro"); setResizable(false); } public static void main (String[] args) { FrameQuatro fr = new FrameQuatro(); fr.setVisible(true); } }

Para que seja possvel essa tarefa de posicionamento conforme a resoluo de vdeo, necessrio obter informaes do sistema operacional, e isso feito atravs da classe Toolkit, mtodo getScreenSize(), cujos dados so jogados em um objeto da classe Dimension, que armazena a altura e largura nos campos d.width e d.height. Por exemplo, se a resoluo de vdeo for 800x600, o d.width fica com 800 e o d.height fica com 600. Tendo esses valores, possvel utilizar em mtodos como o setLocation() e o setSize(), como foi feito no exemplo. Alm disso, o exemplo tambm acrescenta um cone ao frame, tambm utilizando a classe Toolkit, 4

mtodo getImage(), para carregar a imagem (extenso .gif) e jogar em um objeto da classe Image, para depois setar o cone atravs do setIconImage(). O mesmo exemplo pode ser feito baseado na biblioteca Swing, classe JFrame, mudando apenas a derivao e importando o pacote javax.swing.*, assim:
import import import public { ... } java.awt.*; java.awt.event.*; javax.swing.*; class FrameQuatro extends JFrame

Os exemplos apresentados nas prximas sees criaro frames baseado na classe JFrame.

1.2 Mostrando Textos e Linhas no Frame


Para que seja possvel mostrar textos em um frame necessrio criar um objeto baseado na classe Graphics, que ser responsvel pelo gerenciamento da rea grfica a ser desenhada, controlando cores, tipos de fontes, etc. A classe Component possui um mtodo paint() que aceita um objeto Graphics como parmetro. Esse mtodo, na classe de origem, no faz nada, por isso ele deve ser sobrescrito com a chamada de mtodos que realizam operaes de escrita, pintura, desenho, etc. Para efetuar a sobreposio do mtodo paint() deve-se ter o cabealho:
public void paint(Graphics g)

A partir disso, mtodos como drawString() e drawLine() podem ser utilizados, como no exemplo a seguir. O resultado apresentado na figura 1.4.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class MostrandoTextos extends JFrame { public MostrandoTextos() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); Toolkit tk = Toolkit.getDefaultToolkit(); Dimension d = tk.getScreenSize(); int screenHeight = d.height; int screenWidth = d.width; setSize(d.width / 2, d.height / 2); setLocation(d.width / 4, d.height / 4); setTitle("Escrevendo Textos"); setResizable(false); } public void paint (Graphics g) { g.drawString("Estou escrevendo no frame", 40, 50); g.drawLine(40, 60, 200, 60); int i = 30; while (i < 150) {

g.drawString("Estou escrevendo no frame", 40+i, 50+i); g.drawLine(40+i, 60+i, 200+i, 60+i); i+=30; } } public static void main (String[] args) { MostrandoTextos fr = new MostrandoTextos(); fr.setVisible(true); } }

Figura 1.4. Frame MostrandoTextos

O mtodo drawString(String s, int x, int y) realiza a mostragem de um texto em uma posio definida por x e y. O mtodo drawLine(int x1, int y1, int x2, int y2) desenha uma linha que inicia nas coordenadas x1,y1 e termina nas coordenadas x2,y2.

1.3 Cores
O mtodo setColor() seleciona a cor que utilizada para todas as operaes de desenho dentro do contexto grfico ou componente. Um parmetro Color define a cor a ser usada, sendo que as treze cores padro, apresentadas na tabela 1.1, esto definidas na classe java.awt.Color.
black blue cyan

(preto)

magenta orange pink red

(magenta)

(azulo) (ciano) (cinza-escuro)

(laranja)

(rosa)

darkGray gray

(vermelho) (branco) (amarelo)

(cinza) (verde)

white

green

yellow

lightGray

(cinza-claro)

Tabela 1.1. Cores definidas em java.awt.Color

Alm das cores pr-definidas, pode-se criar novas cores baseadas no contedo RGB (redvermelho, green-verde, blue-azul), expressos por inteiros de 0 a 255. O exemplo a seguir apresenta a criao de objetos coloridos em um frame. O resultado apresentado na figura 1.5.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Cores extends JFrame { public Cores() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400, 200); setLocation(200, 100); setTitle("Cores"); } public void paint (Graphics g) { g.setColor(Color.blue); g.drawString("Cor Azul", 50, 50); g.setColor(Color.green); g.drawLine(50, 60, 220, 60); g.setColor(Color.red); g.drawRect(50,70,100,30); g.setColor(new Color(0,128,128)); g.fillRect(50,110,100,30); } public static void main (String[] args) { Cores fr = new Cores(); fr.setVisible(true); } }

Figura 1.5. Frame Cores

O mtodo drawRect(int x, int y, int width, int height) desenha um retngulo com a cor definida em setColor(), iniciando nas coordenadas x,y, tendo uma largura width e uma altura height. O mtodo fillRect(int x, int y, int width, int height) faz a mesma coisa, mas preenche o retngulo.

1.4 Fontes
O mtodo responsvel por definir o tipo de fonte desejado o setFont(), que precisa de um objeto criado, baseado na classe Font, definindo assim o nome da fonte, o seu estilo e seu tamanho. O nome pode ser qualquer fonte suportada pelo sistema operacional especfico; o estilo pode ser: PLAIN regular, BOLD negrito e ITALIC itlico, sendo possvel combinar os estilos utilizando o operador +; o tamanho pode ser qualquer valor que represente o tamanho em pontos da fonte. Exemplo:
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Fontes extends JFrame { public Fontes() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,130); setTitle("Tipos de Fonte"); } public void paint (Graphics g) { g.setColor(Color.blue); Font f = new Font("SansSerif", Font.ITALIC, 16); g.setFont(f); g.drawString("Fonte SansSerif itlico tamanho 16", 20, 50); g.setFont(new Font("Monospaced", Font.BOLD + Font.ITALIC, 14)); g.drawString("Fonte Monospaced negrito e itlico tamanho 14", 20, 80); g.setFont(f); g.drawString("Novamente Fonte SansSerif itlico tamanho 16", 20, 110); } public static void main (String[] args) { Fontes fr = new Fontes(); fr.setVisible(true); } }

A figura 1.6 mostra o resultado. Percebe-se que no necessrio criar explicitamente um objeto do tipo Font (objeto f), podendo ser possvel cri-lo no prprio argumento do setFont(). Se a fonte for utilizada vrias vezes no decorrer da aplicao, torna-se til a criao do objeto explicitamente.

Figura 1.6. Frame Fontes

Em termos de portabilidade, deve-se tomar cuidado quanto a fontes que no existem em alguns sistemas operacionais. O ideal trabalhar com fontes comuns em sistemas operacionais diferentes. O modelo do AWT define cinco fontes disponveis em qualquer sistema operacional. So elas: Serif, Monospaced, SansSerif, Dialog e DialogInput.

1.5 Outras Formas Geomtricas


Alm das formas j apresentadas, existem vrias outras possveis, a maioria com a opo de preenchimento ou no, a partir da precedncia de draw ou fill. O exemplo a seguir tem como resultado o frame apresentado na figura 1.7.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class FormasGeometricas extends JFrame { public FormasGeometricas() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(460,140); setTitle("Formas Geomtricas"); } public void paint (Graphics g) { g.setColor(Color.red); g.drawRoundRect(10,30,80,40,30,30); g.fillRoundRect(10,80,80,40,30,30); g.setColor(Color.yellow); g.draw3DRect(100,30,80,40,true); g.fill3DRect(100,80,80,40,false); g.setColor(Color.blue); g.drawOval(190,30,80,40); g.fillOval(190,80,80,40); g.setColor(Color.darkGray); g.drawArc(280,30,80,40,90,270); g.fillArc(280,80,80,40,90,270); g.setColor(Color.magenta); int ValoresX[] = {370,450,410,370}; int ValoresY[] = {30,30,70,30}; g.drawPolygon(ValoresX,ValoresY,3); int ValoresX2[] = {370,450,410,370}; int ValoresY2[] = {80,80,120,80}; g.fillPolygon(ValoresX2,ValoresY2,3);

} public static void main (String[] args) { FormasGeometricas fr = new FormasGeometricas(); fr.setVisible(true); } }

Figura 1.7. Frame Fontes

Vrias formas geomtricas foram desenhadas no frame. Funcionamento de cada mtodo:


drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight): Desenha um retngulo com cantos arredondados, iniciando nas coordenadas x,y, tendo uma largura width e uma altura height, e cantos definidos por arcWidth e arcHeight. fillRoundRect(int x, int y, int width, int height, arcHeight): Idem a drawRoundRect, mas preenche o retngulo. int arcWidth, int

draw3DRect(int x, int y, int width, int height, boolean raised): Desenha um retngulo 3D, iniciando nas coordenadas x,y, tendo uma largura width e uma altura height, e um valor lgico para indicar a aparncia do 3D. fill3DRect(int x, int y, int width, int height, boolean raised): draw3DRect, mas preenche o retngulo.

Idem a

drawOval(int x, int y, int width, int height): Desenha uma forma oval, baseado nas coordenadas do retngulo que inicia em x,y, tendo uma largura width e uma altura height. fillOval(int x, int y, int width, int height):

Idem a drawOval, mas preenche

a forma oval.
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle): Desenha um arco, baseado nas coordenadas do retngulo que inicia em x,y, tendo uma largura width e uma altura height, mostrando apenas a linha que vai do ngulo startAngle at o ngulo arcAngle. fillArc(int x, arcAngle): Idem int y, int width, int height, int startAngle, int

a drawArc, mas preenche o arco. 10

drawPolygon(int[] xPoints,

int[] yPoints,

int nPoints):

Desenha Idem

um a

polgono, baseado nas coordenadas dos arranjos x,y.


fillPolygon(int[] xPoints, int[] yPoints, drawPolygon, mas preenche o arco. int nPoints):

1.6 Imagens
A classe Image a responsvel pelo carregamento de imagens armazenadas em disco. Novamente, necessrio utilizar um objeto do tipo Toolkit para obter uma imagem, atravs do mtodo getImage(), e depois jogar em um objeto do tipo Image. O exemplo a seguir mostra a maneira de se preencher um frame com as imagens lado a lado. A figura 1.8 mostra o resultado.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Imagens extends JFrame { public Imagens() //construtora { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,200); setTitle("Imagens"); } public void paint (Graphics g) { Image ima = Toolkit.getDefaultToolkit().getImage("LogoJava.gif"); int larguraTela = 400; int alturaTela = 200; int larguraImagem = ima.getWidth(this); int alturaImagem = ima.getHeight(this); g.drawImage(ima,4,23,null); for (int i = 0; i <= larguraTela / larguraImagem; i++) for (int j = 0; j <= alturaTela / alturaImagem; j++) if (i + j > 0) g.copyArea(4,23,larguraImagem, alturaImagem, i * larguraImagem, j * alturaImagem); } public static void main (String[] args) { Imagens fr = new Imagens(); fr.setVisible(true); } }

11

Figura 1.8. Frame Imagens

A primeira imagem, obtida pelo getImage() e jogada no objeto Image ima, mostrada a partir do drawImage(Image img, int x, int y, ImageObserver observer), que insere a imagem img nas coordenadas x,y, para depois ser copiada lado a lado, atravs do mtodo copyArea(int x, int y, int width, int height, int dx, int dy), que copia o contedo da rea que comear nas coordenadas x,y com largura width e altura height, em um local a uma distncia dx,dy. Para realizar essa tarefa, foi necessrio descobrir o tamanho da imagem, atravs getWidth() e do getHeight().

1.7 Continers
Continers servem de repositrio de outros componentes, como botes, por exemplo. Alguns exemplos de continers: JFrame, JPanel e JApplet. Um JFrame uma janela de mais alto nvel; um JPanel um continer usado para agrupar componentes, normalmente dentro de um JFrame; um JApplet permite a execuo em navegadores da Web. Pode-se desenhar algo diretamente no frame ou definir um continer, como um painel, por exemplo, e desenhar nele. No considerada uma boa prtica de programao desenhar diretamente no frame, pois ele foi projetado para ser continer de componentes especficos, como barras de menu, por exemplo. Os painis devem ser utilizados para agrupar outros componentes. Exemplo de adio de um painel a um frame:
import java.awt.*; import java.awt.event.*; import javax.swing.*; class Painel extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("Estou escrevendo em um painel", 100, 50); } } public class EscrevendoEmPainel extends JFrame { public EscrevendoEmPainel() { addWindowListener(new WindowAdapter()

12

{public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,130); setTitle("Painel"); Container P = getContentPane(); P.add(new Painel()); } public static void main (String[] args) { EscrevendoEmPainel fr = new EscrevendoEmPainel(); fr.setVisible(true); } }

Figura 1.9. Continer do tipo painel

O resultado pode ser conferido na figura 1.9. Para desenhar algo em um painel, deve-se criar uma classe derivada de JPanel e sobrepor o mtodo paintComponent(), que est definido na classe JComponent, e recebe um parmetro do tipo Graphics. Tal mtodo chamado automaticamente toda vez que a janela redesenhada, como na criao e no redimensionamento. Se, por algum motivo, se desejar redesenhar o contedo no painel, o mtodo a ser chamado o repaint(), que se encarrega de executar novamente o paintComponent(). O super.paintComponent(g) faz com que o mtodo da superclasse seja executado tambm. Isso normalmente feito em sobreposies de mtodos, quando se deseja criar algo a mais que o mtodo definido na superclasse. A criao de uma classe derivada de JFrame feita a seguir, e um objeto Container criado para depois adicionar (add) o painel. O mtodo getContentPane() retorna a rea de contedo do frame para que possa ser adicionado o painel.

1.8 Gerenciadores de Layout


Os gerenciadores de layout controlam o dimensionamento e posicionamento dos componentes dentro de continers, sendo que cada continer possui um gerenciador padro, mas pode ser alterado atravs da chamada ao mtodo setLayout() do continer especfico. Por exemplo, o gerenciador padro do JPanel o FlowLayout, que coloca os componentes em um tamanho prdefinido da esquerda para a direita e de cima para baixo no continer. Outros gerenciadores de layout existentes: GridLayout, BorderLayout, BoxLayout e GridBagLayout. 1.8.1 Gerenciador FlowLayout

Para que seja possvel verificar a diferena entre alguns deles, exemplos so demonstrados nas prximas sees, comeando exatamente pelo gerenciador FlowLayout, padro do JPanel. Nos exemplos, so definidos objetos boto a partir da classe JButton.
import java.awt.*;

13

import java.awt.event.*; import javax.swing.*; class PainelFlow extends JPanel { public PainelFlow() { setLayout(new FlowLayout()); add(new JButton("Um")); add(new JButton("Dois")); add(new JButton("Trs")); add(new JButton("Quatro")); add(new JButton("Cinco")); } } public class GerenciadorFlowLayout extends JFrame { public GerenciadorFlowLayout() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(200,90); setLocation(150,150); setTitle("FlowLayout"); Container P = getContentPane(); P.add(new PainelFlow()); } public static void main (String[] args) { GerenciadorFlowLayout fr = new GerenciadorFlowLayout(); fr.setVisible(true); } }

Figura 1.10. Gerenciador de Layout FlowLayout

Como o FlowLayout o gerenciador padro do JPanel, no seria necessrio setar o layout atravs do setLayout(new FlowLayout());. O alinhamento dos componentes fica centralizado e, caso algum compontnte no caiba em uma linha, jogado para a linha seguinte, como mostra a figura 1.10. possvel alterar o alinhamento, passando-o como parmetro na determinao do layout (LEFT, RIGHT ou CENTER), assim:
setLayout(new FlowLayout(FlowLayout.RIGHT));

1.8.2

Gerenciador GridLayout

14

O GridLayout um gerenciador que organiza os componentes em linhas e colunas espaadas regularmente. Exemplo:
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelGrid extends JPanel { public PainelGrid() { setLayout(new GridLayout(3,2)); add(new JButton("Um")); add(new JButton("Dois")); add(new JButton("Trs")); add(new JButton("Quatro")); add(new JButton("Cinco")); } } public class GerenciadorGridLayout extends JFrame { public GerenciadorGridLayout() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(200,150); setLocation(150,150); setTitle("GridLayout"); Container P = getContentPane(); P.add(new PainelGrid()); } public static void main (String[] args) { GerenciadorGridLayout fr = new GerenciadorGridLayout(); fr.setVisible(true); } }

Figura 1.11. Gerenciador de Layout GridLayout

O tamanho de cada componente redimensionado automaticamente, como mostra a figura 1.11, podendo ficar espaos vazios. necessrio definir o nmero de linhas e colunas no

15

setLayout().

Os componentes so adicionados a partir da posio na parte superior esquerda da grade, seguindo para a direita at preencher a linha e passar para baixo.

Tambm possvel espaar os componentes horizontal e verticalmente. Nesse caso, na definio do layout, deve-se passar esses valores tambm. O layout abaixo, por exemplo, define 5 pixels de espaameno horizontal e 8 pixels de espaamento vertical:
setLayout(new GridLayout(3,2,5,8));

1.8.3

Gerenciador BorderLayout

Existem gerenciadores mais interessantes, como o BorderLayout, que organiza os objetos em locais determinados por NORTH, SOUTH, EAST, WEST e CENTER. Exemplo:
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelBorder extends JPanel { public PainelBorder() { setLayout(new BorderLayout()); add(new JButton("Um"),BorderLayout.NORTH); add(new JButton("Dois"),BorderLayout.SOUTH); add(new JButton("Trs"),BorderLayout.EAST); add(new JButton("Quatro"),BorderLayout.WEST); add(new JButton("Cinco"),BorderLayout.CENTER); } } public class GerenciadorBorderLayout extends JFrame { public GerenciadorBorderLayout() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,150); setLocation(150,150); setTitle("BorderLayout"); Container P = getContentPane(); P.add(new PainelBorder()); } public static void main (String[] args) { GerenciadorBorderLayout fr = new GerenciadorBorderLayout(); fr.setVisible(true); } }

16

Figura 1.12. Gerenciador de Layout GridLayout

Na figura 1.12 se observa o resultado da aplicao, com um boto em cada localizao geogrfica dentro do painel. O BorderLayout o gerenciador padro para os continers JWindow e JFrame. No necessrio ter todas as localizaes preenchidas. Se alguma das localizaes (norte, sul, leste ou oeste) no for ocupada, as demais ocupam o lugar da(s) omitida(s). Porm, se a localizao central no for ocupada, ela ficar vazia. Na definio do layout possvel determinar o espaamento horizontal e vertical entre as localizaes. O layout abaixo, por exemplo, define 5 pixels de espaameno horizontal e 8 pixels de espaamento vertical:
setLayout(new BorderLayout(5,8));

1.8.4

Gerenciador BoxLayout

Os gerenciadores de layout foram criados ainda na verso 1.0 do Java. O Swing possui apenas um gerenciador de layout de uso geral, chamado BoxLayout, sendo mais utilizado para criar barras de ferramentas, podendo inserir componentes em apenas uma linha ou uma coluna. Ao invs de utilizar o BoxLayout diretamente, pode-se usar um outro continer do Swing chamado Box, como no exemplo a seguir.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelBox extends JPanel { public PainelBox() { add(Box.createHorizontalGlue()); add(new JButton("Um")); add(Box.createHorizontalGlue()); add(new JButton("Dois")); add(Box.createHorizontalStrut(10)); add(new JButton("Trs")); add(Box.createHorizontalStrut(30)); add(new JButton("Quatro")); add(Box.createHorizontalGlue()); add(new JButton("Cinco")); add(Box.createHorizontalGlue()); } } public class GerenciadorBoxLayout extends JFrame

17

{ public GerenciadorBoxLayout() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(500,100); setLocation(150,150); setTitle("BoxLayout"); Container b = Box.createHorizontalBox(); getContentPane().add(b,BorderLayout.CENTER); b.add(new PainelBox()); } public static void main (String[] args) { GerenciadorBoxLayout fr = new GerenciadorBoxLayout(); fr.setVisible(true); } }

Figura 1.13. Gerenciador de Layout BoxLayout

Observa-se, na figura 1.13, que os botes no ficaram distanciados uniformemente. Isso porque dois mtodos foram utilizados: o createHorizontalGlue(), que determina um espaamento varivel, conforme o tamanho da janela e o createHorizontalStrut(), que determina um espaamento fixo, determinado pelo seu parmetro. 1.8.5 Gerenciador GridBagLayout

O gerenciador GridBagLayout bastante flexvel, permitindo posicionamento dos componentes em relao aos outros. Assim, possvel criar praticamente qualquer tipo de layout. Por ser mais flexvel, tambm mais difcil de ser utilizado. O construtor no possui argumentos e a aparncia do layout controlada pela classe GridBagConstraints. Os componentes gerenciados devem estar associados a um objeto GridBagConstraints, que possui campos, mostrados na tabela 1.1, para controle dos componentes. Campo
int gridx, gridy int weightx, weighty

Descrio Utilizado para controlar o posicionamento dos componentes na grade do layout. Utilizado para especificar um percentual de aumento do local destinado aos componentes, que iro aumentar tambm se estiverem expandidos. Utilizado para expandir o componente a fim de preencher o espao reservado a ele. Utilizado para indicar o nmero de linhas ou colunas que o

int fill int gridheight, gridwidth

18

int anchor int ipadx, ipady Insets insets

componente ir se espalhar. Utilizado para controlar a posio do componente, caso ele no esteja espalhado. Utilizado para controlar o aumento do tamanho mnimo dos componente. Utilizado para controlar o afastamento entre componentes.
Tabela 1.1. Campos da classe GridBagConstraints

A utilizao desses campos so demonstradas atravs de exemplos. O primeiro deles mostra um GridBagLayout com cinco botes inseridos em posies determinadas pelo gridx e gridy.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelGridBag extends JPanel { GridBagConstraints restricoes = new GridBagConstraints(); public PainelGridBag() { setLayout(new GridBagLayout()); addGridBag(new JButton("Um"), 1, 0); addGridBag(new JButton("Dois"), 0, 1); addGridBag(new JButton("Trs"), 1, 1); addGridBag(new JButton("Quatro"), 2, 1); addGridBag(new JButton("Cinco"), 1, 2); } void addGridBag(Component objeto, int x, int y) { restricoes.gridx = x; restricoes.gridy = y; add(objeto, restricoes); } } public class GerenciadorGridBagLayout extends JFrame { public GerenciadorGridBagLayout() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(270,130); setLocation(150,150); setTitle("GridBagLayout"); Container P = getContentPane(); P.add(new PainelGridBag()); } public static void main (String[] args) { GerenciadorGridBagLayout fr = new GerenciadorGridBagLayout(); fr.setVisible(true);

19

} }

Figura 1.13. Gerenciador de Layout GridBagLayout com cinco botes

O resultado, mostrado na figura 1.13, apresenta cinco botes inseridos em coordenadas que indicam a presena de trs linhas por trs colunas (0, 1 e 2). O tamanho da grade definido por essas coordenadas, sendo possvel, por isso, ter quantas colunas e linhas se desejar. O mtodo addGridBag() criado serve para auxiliar na definio dos valores que os campos de controle do GridBagConstraints iro assumir. Para que os botes preencham toda a rea do painel necessrio definir, no construtor, a restrio fill para BOTH e os campos weigthx e weigthy para 1, assim:
public PainelGridBag() { setLayout(new GridBagLayout()); restricoes.weightx = 1.0; restricoes.weighty = 1.0; restricoes.fill = GridBagConstraints.BOTH; addGridBag(new JButton("Um"), 1, 0); addGridBag(new JButton("Dois"), 0, 1); addGridBag(new JButton("Trs"), 1, 1); addGridBag(new JButton("Quatro"), 2, 1); addGridBag(new JButton("Cinco"), 1, 2); }

Figura 1.14. Gerenciador de Layout GridBagLayout ocupando todo espao disponvel

O resultado o preenchimento de todo painel, como mostra a figura 1.14. O fill ainda pode ser definido como: HORIZONTAL, preenchendo o espao horizontal disponvel; VERTICAL, preenchendo o espao vertical disponvel e; NONE, no preenchendo o espao disponvel. Os campos weigthx e weigthy devem receber um valor diferente de zero, pois o preenchimento no ocorre se esse valor for igual a zero, que o valor default. possvel realizar um espalhamento dos componentes em mais do que uma linha e/ou coluna. Para isso, necessrio combinar os valores de gridx e gridy com a determinao da altura (em

20

nmero de linhas) e largura (em nmero de colunas) atravs dos campos gridwidth e gridheight, assim:
public PainelGridBag() { setLayout(new GridBagLayout()); restricoes.weightx = 1.0; restricoes.weighty = 1.0; restricoes.fill = GridBagConstraints.BOTH; restricoes.gridwidth = 3; addGridBag(new JButton("Um"), 0, 0); restricoes.gridwidth = 1; addGridBag(new JButton("Dois"), 0, 1); addGridBag(new JButton("Trs"), 1, 1); restricoes.gridheight = 2; addGridBag(new JButton("Quatro"), 2, 1); restricoes.gridheight = 1; addGridBag(new JButton("Cinco"), 0, 2); addGridBag(new JButton("Seis"), 1, 2); }

Figura 1.15. Gerenciador de Layout GridBagLayout utilizando espalhamento

Percebe-se, pelo resultado apresentado na figura 1.15, que o boto Um ocupou trs colunas e uma linha, enquanto o boto Quatro ocupou duas linhas e uma coluna. No momento que o nmero de colunas/linhas definido, todos os componentes utilizaro esse tamanho de espao da pra diante, a no ser que este seja redefinido. possvel tambm definir o tamanho dos componentes atravs do peso atribudo aos campos weigthx e weigthy, como no exemplo:
public PainelGridBag() { setLayout(new GridBagLayout()); restricoes.weighty = 1.0; restricoes.fill = GridBagConstraints.BOTH; restricoes.weightx = 0.2; addGridBag(new JButton("Um"), 0, 0); restricoes.weightx = 0.6; addGridBag(new JButton("Dois"), 1, 0); restricoes.weightx = 1.5; addGridBag(new JButton("Trs"), 2, 0); restricoes.weightx = 4.0; addGridBag(new JButton("Quatro"), 3, 0); }

21

Figura 1.16. Gerenciador de Layout GridBagLayout com determinao de pesos

Para que o exemplo fique igual ao apresentado na figura 1.16, necessrio mudar o setSize() do frame para (400,60). Os botes ficam dispostos em uma nica linha, com tamanhos diferentes, determinados pela atribuio de seus respectivos pesos, sabendo-se que o valor especfico do peso no o que importa, e sim as propores relativas entre os botes e o tamanho do painel. O aumento do tamanho de alguns componentes pode ser feito pelos campos ipadx e ipady, que especificam valores de aumento vertical e horizontal. Alm disso, possvel fixar uma posio do componente, dentro do espao reservado a ele, desde que ele no esteja espalhado em mais que uma coluna e/ou linha. Isso feito atravs do anchor. Exemplo:
public PainelGridBag() { setLayout(new GridBagLayout()); addGridBag(new JButton("Um"), 1, 0); restricoes.ipadx=10; restricoes.ipady=10; addGridBag(new JButton("Dois"), 0, 1); restricoes.ipadx=0; restricoes.ipady=0; restricoes.anchor = GridBagConstraints.SOUTHEAST; addGridBag(new JButton("Trs"), 1, 1); restricoes.ipadx=10; restricoes.ipady=10; restricoes.anchor = GridBagConstraints.CENTER; addGridBag(new JButton("Quatro"), 2, 1); restricoes.ipadx=0; restricoes.ipady=0; addGridBag(new JButton("Cinco"), 1, 2); }

Figura 1.17. Gerenciador de Layout GridBagLayout com aumento do tamanho e posicionamento de componentes

Novamente, para que o exemplo fique igual ao da figura 1.17, necessrio alterar o setSize() do frame para (270,130). Percebe-se que o tamanho dos componentes Dois e Quatro foi aumentado, sendo mantido o tamanho mnimo do boto Trs. Para esse mesmo boto Trs foi especificado um posicionamento fixo no canto inferior direito, dentro de sua rea definida. O anchor s pode ser utilizado quando o tamanho do componente for menor que a rea que lhe foi

22

concedida. O valor padro CENTER, e os outros valores possveis so: NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, e NORTHWEST. Atravs do campo insets possvel indicar as distncias entre os componentes do layout. Uma classe Insets possui valores para as quatro direes: cima, baixo, direita e esquerda, dando muita flexibilidade ao layout. O valor padro (0, 0, 0, 0). Exemplo:
public PainelGridBag() { setLayout(new GridBagLayout()); restricoes.weightx = 1.0; restricoes.weighty = 1.0; restricoes.fill = GridBagConstraints.BOTH; restricoes.insets = new Insets(3,3,3,3); addGridBag(new JButton("Um"), 1, 0); addGridBag(new JButton("Dois"), 0, 1); addGridBag(new JButton("Trs"), 1, 1); addGridBag(new JButton("Quatro"), 2, 1); addGridBag(new JButton("Cinco"), 1, 2); }

Figura 1.18. Gerenciador de Layout GridBagLayout utilizando Insets

A figura 1.18 mostra que cada componente ganhou um espao adicional de trs pixels para cada uma das direes: cima, baixo, direita e esquerda. 1.8.6 Layouts Compostos

Normalmente, ao querer criar um determinado layout, a utillizao de um gerenciador apenas no suficiente. necessrio, ento, combinar os diferentes layouts, como no exemplo a seguir.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelComposto extends JPanel { public PainelComposto() { setLayout(new BorderLayout()); add(new JTextField("Digite seu texto aqui"),BorderLayout.NORTH); add(new PainelTipoFlow(),BorderLayout.SOUTH); } } class PainelTipoFlow extends JPanel {

23

public PainelTipoFlow() { setLayout(new FlowLayout()); add(new JButton("Um")); add(new JButton("Dois")); add(new JButton("Trs")); add(new JButton("Quatro")); add(new JButton("Cinco")); } } public class LayoutsCompostos extends JFrame { public LayoutsCompostos() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,120); setLocation(150,150); setTitle("Layouts Compostos"); Container P = getContentPane(); P.add(new PainelComposto()); } public static void main (String[] args) { LayoutsCompostos fr = new LayoutsCompostos(); fr.setVisible(true); } }

Figura 1.17. Layouts Compostos BorderLayout e FlowLayout

A figura 1.17 mostra que o painel com layout FlowLayout foi inserido na localizao sul do painel com layout BorderLayout. Isso uma prtica bastante comum para se alcanar layouts com disposio de componentes que satisfaam aos objetivos da aplicao. A localizao do centro ficou vazia porque isso uma caracterstica do BorderLayout: no expandir as outras localizaes se a do centro estiver vazia.

2. Interface Grfica com o Usurio e a Manipulao de Eventos


Os componentes de uma Interface Grfica com o Usurio (GUI) so baseados em eventos, os quais so gerados na interao do usurio com a interface. Alguns exemplos de eventos possveis: mover/clicar o mouse, clicar em um boto, fechar o frame, digitar um texto em um campo de edio, etc. necessrio, ento, realizar uma manipulao dos eventos gerados. As prximas

24

sees descrevem o modelo de manipulao de eventos AWT a partir de alguns elementos GUI simples.

2.1 O Modelo de Manipulao de Eventos AWT


muito comum encontrar, em linguagens de programao visuais, o tratamento dos eventos que so gerados por seus componentes visuais. Com Java no diferente, tanto na biblioteca AWT, quanto na biblioteca Swing, existem classes para manipulao de eventos. A maneira como essa manipulao acontece no to simples como nas linguagens Delphi e Visual Basic, exigindo que haja a designao de pelo menos um (pode ter mais que um) objeto ouvinte de eventos, que deve ser um objeto de uma classe que implemente a interface ouvinte (listener interface). O objeto deve efetuar convenientemente a resposta desejada ao evento. necessrio lembrar que as interfaces possuem mtodos abstract para serem redefinidos pelas classes que as implementarem. Alm disso, todos os mtodos abstract devem ser redefinidos. O registro desses ouvintes feito em objetos conhecidos como origem do evento, como um boto, por exemplo. A origem envia objetos eventos para o(s) ouvinte(s) na ocorrncia de um evento, e esse(s) usa(m) essa informao para determinar o que ser feito em reao ao evento. Um exemplo de registro de um objeto ouvinte painel em um objeto de origem boto:
MeuPainel painel = new MeuPainel(); Jbutton botao = new Jbutton(OK); botao.addActionListener(painel);

seguindo a sintaxe:
ObjetoOrigem.addEventListener(ObjetoOuvinte);

Assim, o objeto painel notificado sempre que um evento ocorrer em botao, como o clique, por exemplo. No exemplo, a classe onde o objeto ouvinte painel registrado deve implementar a interface ActionListener e definir o mtodo actionPerformed(), que recebe um objeto ActionEvent como parmetro. Assim:
public class MeuPainel extends Jpanel implements ActionListener { ... public void actionPerformed(ActionEvent evt) { //cdigo para a reao ao evento } }

2.2 Eventos em Botes


O exemplo a seguir apresenta um painel com trs botes, sendo que o prprio painel definido como ouvinte para monitorar os eventos que podem acontecer nos botes.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelEventosBotao extends JPanel implements ActionListener { private JButton BotaoVerde; private JButton BotaoPreto;

25

private JButton BotaoBranco; public PainelEventosBotao() { BotaoVerde = new JButton("Verde"); BotaoPreto = new JButton("Preto"); BotaoBranco = new JButton("Branco"); add(BotaoVerde); add(BotaoPreto); add(BotaoBranco); BotaoVerde.addActionListener(this); BotaoPreto.addActionListener(this); BotaoBranco.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); Color cor = getBackground(); if (origem == BotaoVerde) cor = Color.green; else if (origem == BotaoPreto) cor = Color.black; else if (origem == BotaoBranco) cor = Color.white; setBackground(cor); repaint(); } } public class TesteEventosBotao extends JFrame { public TesteEventosBotao() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,130); setTitle("Eventos em Botes"); Container P = getContentPane(); P.add(new PainelEventosBotao()); } public static void main(String[] args) { JFrame fr = new TesteEventosBotao(); fr.setVisible(true); } }

26

Figura 2.1. Eventos em objetos JButton

Na criao do painel, trs botes foram adicionados a ele. Logo aps, foi determinado que o prprio painel (this) seria o ouvinte das aes dos trs botes. O mtodo actionPerformed() o nico mtodo da interface ActionListener, por isso apenas ele deve ser implementado. Esse mtodo recebe como parmetro um objeto do tipo ActionEvent, que fornece informaes sobre o evento ocorrido, sendo o local para implementar as aes a serem realizadas. A classe TesteEventosBotao adiciona o painel com os botes.

2.3 Eventos em Caixas de Texto


O exemplo a seguir apresenta um painel com duas caixas de texto do tipo JTextField e uma do tipo JPasswordField. O objeto ouvinte definido foi o prprio painel e, quando for dado um Enter em qualquer uma das caixas, o contedo digitado ir aparecer em uma caixa de mensagens.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelEventosCaixaTexto extends JPanel implements ActionListener { private JTextField Codigo; private JTextField Nome; private JPasswordField Senha; public PainelEventosCaixaTexto() { Codigo = new JTextField(3); add(Codigo); Nome = new JTextField("Digite seu nome"); add(Nome); Senha = new JPasswordField(10); add(Senha); Codigo.addActionListener(this); Nome.addActionListener(this); Senha.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == Codigo) JOptionPane.showMessageDialog(null,"Cdigo = "+ evt.getActionCommand()); else if (origem == Nome) JOptionPane.showMessageDialog(null,"Nome = "+ evt.getActionCommand()); else if (origem == Senha) JOptionPane.showMessageDialog(null,"Senha = "+ evt.getActionCommand()); } } public class TesteEventosCaixaTexto extends JFrame { public TesteEventosCaixaTexto() { addWindowListener(new WindowAdapter()

27

{public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,70); setLocation(300,350); setTitle("Eventos em Caixas de Texto"); Container P = getContentPane(); P.add(new PainelEventosCaixaTexto()); } public static void main(String[] args) { JFrame fr = new TesteEventosCaixaTexto(); fr.setVisible(true); } }

Figura 2.2. Eventos em objetos JTextField e JPasswordField

A figura 2.1 mostra o que acontece se for digitado algo em cdigo e logo a seguir for pressionada a tecla Enter. Novamente, o mtodo actionPerformed() foi sobreposto e, no momento que for pressionado o Enter, o getSource() pega o objeto onde est o foco naquele momento e mostra em uma caixa de mensagens, criada a partir do mtodo showMessageDialog(), pertencente classe JOptionPane.

2.4 Utilizando Eventos para Alterar o Aspecto Visual da Aplicao


O Look and Feel a aparncia que sua aplicao ir tomar, definindo a forma como seus componentes sero mostrados na tela. Ao utilizar componentes da biblioteca Swing, o aspecto visual determinado pelo estilo Metal, mas existem outros, e a alterao feita atravs do mtodo UIManager.setLookAndFeel(), passando como parmetro o aspecto visual desejado, localizados em pacotes diferentes: Aspecto Metal: javax.swing.plaf.metal.MetalLookAndFeel Aspecto Windows: com.sun.java.swing.plaf.windows.WindowsLookAndFeel Aspecto Motif: com.sun.java.swing.plaf.motif.MotifLookAndFeel Aspecto GTK: com.sun.java.swing.plaf.gtk.GTKLookAndFeel Aspecto Mac: javax.swing.plaf.mac.MacLookAndFeel

Logo aps, necessrio chamar o mtodo SwingUtilities.updateComponentTreeUI para atualizar todo o conjunto de componentes.
import java.awt.*; import java.awt.event.*;

28

import javax.swing.*; class PainelAV extends JPanel implements ActionListener { private JButton BotaoMetal; private JButton BotaoWindows; private JButton BotaoMotif; private JButton BotaoGTK; private JButton BotaoMac; private JTextField Texto; public PainelAV() { BotaoMetal = new JButton("Metal"); BotaoWindows = new JButton("Windows"); BotaoMotif = new JButton("Motif"); BotaoGTK = new JButton("GTK"); BotaoMac = new JButton("Mac"); Texto = new JTextField("Digite seu texto aqui"); add(BotaoMetal); add(BotaoWindows); add(BotaoMotif); add(BotaoGTK); add(BotaoMac); add(Texto); BotaoMetal.addActionListener(this); BotaoWindows.addActionListener(this); BotaoMotif.addActionListener(this); BotaoGTK.addActionListener(this); BotaoMac.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); String modelo = ""; if (origem == BotaoMetal) modelo = "javax.swing.plaf.metal.MetalLookAndFeel"; else if (origem == BotaoWindows) modelo = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; else if (origem == BotaoMotif) modelo = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; else if (origem == BotaoGTK) modelo = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; else if (origem == BotaoMac) modelo = "javax.swing.plaf.mac.MacLookAndFeel"; try { UIManager.setLookAndFeel(modelo); SwingUtilities.updateComponentTreeUI(this); } catch (Exception e) {} } } public class AspectosVisuais extends JFrame { public AspectosVisuais()

29

{ addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(370,100); setTitle("Aspectos Visuais"); Container P = getContentPane(); P.add(new PainelAV()); } public static void main(String[] args) { JFrame fr = new AspectosVisuais(); fr.setVisible(true); } }

Figura 2.3. Aspectos Visuais Metal, Windows, Motif, GTK e Mac

A figura 2.3 mostra e resultado da execuo aps selecionar cada um dos aspectos visuais. importante salientar que o aspecto Windows s funciona no prprio Windows, pois a Sun no disponibiliza esse aspecto para outras plataformas. Alguns Look And Feels podem gerar uma exceo, por no existirem ou no serem suportados em determinadas plataformas, como o que ocorreu como aspecto Mac. importante salientar tambm que, a depender do layout utilizado em uma determinada aplicao, podem ocorrer problemas de aparncia, por que tamanhos de botes, caixas de texto e outros componentes variam de plataforma para plataforma, e podem fazer com que a aparncia de uma aplicao fique desorganizada, como o que ocorreu com o aspecto GTK. Muitos aspectos interessantes podem ser encontrados na Internet.

2.5 Resumo de Eventos no AWT


A tabela 2.1 mostra todas as interfaces da AWT existentes para serem implementadas em classes com objetos ouvintes, os mtodos que devem ser sobrepostos, os parmetros e os objetos origens dos eventos. Interface
ActionListener

Mtodos
actionPerformed

Parmetros
ActionEvent getActionCommand getModifiers

Origens
Button List MenuItem TextField Scrollbar

AdjustmentListener

AdjustementValueChanged AdjustmentEvent getAdjustable

30

ItemListener

ItemStateChanged

TextListener ComponentListenter

ContainerListener

TextValueChanged componentMoved componentHidden componentResized componentShown componentAdded componentRemoved focusGained focusLost keyPressed keyReleased keyTyped

getAdjustmentType getValue ItemEvent getItem getItemSelectable getStateChange TextEvent ComponentEvent getComponent

Checkbox CheckboxMenuItem Choice List TextComponent Component

FocusListener KeyListener

MouseListener

mousePressed mouseReleased mouseEntered mouseExited mouseClicked

MouseMotionListener mouseDragged mouseMoved WindowListener windowClosing windowOpened windowIconified windowDeiconified windowClosed windowActivated windowDeactivated

ComponentEvent getChild getContainer FocusEvent isTemporary KeyEvent getKeyChar getKeyCode getKeyModifiersText getKeyText isActionKey MouseEvent getClickCount getX getY getPoint translatePoint isPopupTrigger MouseEvent WindowEvent getWindow

Container

Component Component

Component

Component Window

Figura 2.3. Interfaces existentes para manipular eventos

Boa parte dos componentes do Swing utilizam essas mesmas interfaces para manipular eventos, mas existem outras. Os pacotes dessas interfaces so: java.awt.event e javax.swing.event.

3. Utilizando a Biblioteca Swing para a Interface com o Usurio


A partir do conhecimento do funcionamento do modelo de eventos possvel utiliza-lo nos muitos componentes de interface com o usurio existentes na biblioteca Swing, como listas, menus e caixas de dilogo, por exemplo. bom lembrar que boa parte desses componentes possui um correspondente no AWT. A diferena que, ao contrrio do AWT, os componentes do Swing so implementados no prprio Java, garantindo que, indiferente da plataforma utilizada, a aparncia no fique prejudicada.

31

As prximas sees se destinam a apresentao dos principais componentes do Swing, alm dos botes e caixas de texto, que foram vistos no captulo anterior.

3.1 Labels e Botes Classes JLabel e JButton


Os labels e botes so componentes muito utilizados e de fcil manipulao. Como j visto, para tratar eventos em botes necessrio implementar o mtodo actionPerformed() da interface ActionListenter. O exemplo a seguir mostra as principais aes que podem ser realizadas em labels, acionadas a partir do clique de botes.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class PainelEventosBotaoELabel extends JPanel implements ActionListener { private JButton BotaoUm; private JButton BotaoDois; private JLabel LabelUm; private JLabel LabelDois; public PainelEventosBotaoELabel() { BotaoUm = new JButton("Um"); BotaoDois = new JButton("Dois"); LabelUm = new JLabel("Label para o boto um"); LabelDois = new JLabel("Label para o boto dois"); add(BotaoUm); add(LabelUm); add(BotaoDois); add(LabelDois); BotaoUm.addActionListener(this); BotaoDois.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); Icon icone = new ImageIcon("LogoJava.gif"); if (evt.getActionCommand().equals("Um")) // primeira maneira de verificar { LabelUm.setText("O boto " + BotaoUm.getText() + " foi clicado"); LabelUm.setIcon(icone); LabelUm.setVerticalTextPosition(SwingConstants.BOTTOM); LabelUm.setHorizontalTextPosition(SwingConstants.RIGHT); } if (origem == BotaoDois) // segunda maneira de verificar { LabelDois.setText("O boto " + BotaoDois.getText() + " foi clicado"); LabelDois.setToolTipText("Esse o label do boto dois"); } } }

32

public class TesteEventosBotaoELabel extends JFrame { public TesteEventosBotaoELabel() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(600,130); setTitle("Botes e Labels"); Container P = getContentPane(); P.add(new PainelEventosBotaoELabel()); } public static void main(String[] args) { JFrame fr = new TesteEventosBotaoELabel(); fr.setVisible(true); } }

Figura 3.1. Manipulao de Botes e Labels

A figura 3.1 mostra a situao aps o clique nos dois botes. No cdigo, percebe-se que existem duas maneiras de saber qual boto foi clicado. A primeira testando o prprio texto do boto, a partir do getActionCommand().equals(). A segunda atravs da definio de um objeto origem, que, atravs do mtodo getSource(), sabe qual boto gerou o evento. No clique do BotaoUm alterado o texto do LabelUm, setado um cone para ele e realizado seu posicionamento horizontal (setHorizontalTextPosition()) e vertical (setVerticalTextPosition()). O clique do BotaoDois altera o texto do LabelUm, alm de utilizar o mtodo setToolTipText() para especificar a dica de ferramenta, que exibida quando o cursor do mouse passa sobre o label.

3.2 Botes de Estado Classes JRadioButton e JCheckBox


Os botes de estado permitem ativar ou desativar opes. Dois tipos so comumente usados: as caixas de seleo e os botes de rdio. Uma caixa de seleo possui um rtulo (label) que a identifica e, ao clicar nela, a opo vai ficar ativada ou no, conforme o estado atual. Botes de rdio ficam agrupados a partir da classe ButtonGroup, sendo que apenas uma opo pode ficar selecionada. Para tratamento dos eventos, a interface utilizada a ActionListener, como nos botes e caixas de texto. Exemplo:
import java.awt.*; import java.awt.event.*; import javax.swing.*;

33

class PainelBotoesDeEstado extends JPanel implements ActionListener { private JTextField Texto; private JCheckBox CBItalico; private JCheckBox CBNegrito; private JRadioButton RBSansSerif; private JRadioButton RBMonospaced; private JRadioButton RBSerif; private ButtonGroup Grupo; public PainelBotoesDeEstado() { Texto = new JTextField("Texto para visualizao",15); CBItalico = new JCheckBox("Itlico"); CBNegrito = new JCheckBox("Negrito"); RBSansSerif = new JRadioButton("SansSerif",true); RBMonospaced = new JRadioButton("Monospaced",false); RBSerif = new JRadioButton("Serif",false); add(Texto); add(CBItalico); add(CBNegrito); add(RBSansSerif); add(RBMonospaced); add(RBSerif); Grupo = new ButtonGroup(); Grupo.add(RBSansSerif); Grupo.add(RBMonospaced); Grupo.add(RBSerif); CBItalico.addActionListener(this); CBNegrito.addActionListener(this); RBSansSerif.addActionListener(this); RBMonospaced.addActionListener(this); RBSerif.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); Font f = Texto.getFont(); String Fonte = f.getName(); int Negrito = Font.PLAIN; int Italico = Font.PLAIN; if (CBItalico.isSelected()) Italico = Font.ITALIC; else Italico = Font.PLAIN; if (CBNegrito.isSelected()) Negrito = Font.BOLD; else Negrito = Font.PLAIN; if (origem == RBSansSerif) Fonte = "SansSerif"; else if (origem == RBMonospaced) Fonte = "Monospaced"; else if (origem == RBSerif) Fonte = "Serif"; Texto.setFont(new Font(Fonte, Negrito + Italico, 12));

34

} } public class BotoesDeEstado extends JFrame { public BotoesDeEstado() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(350,100); setTitle("Botes de Estado"); Container P = getContentPane(); P.add(new PainelBotoesDeEstado()); } public static void main(String[] args) { JFrame fr = new BotoesDeEstado(); fr.setVisible(true); } }

Figura 3.2. Botes de Estado

A figura 3.2 apresenta o resultado da execuo do exemplo, j com alguns itens selecionados. Ao clicar em uma caixa de seleo, acionado um evento de ao, capturado no mtodo actionPerformed(). O mtodo isSelect() retorna o estado atual da caixa de seleo e, conforme o estado, as variveis Italico e Negrito so atualizadas, para depois servirem de parmetro para a alterao da fonte a partir do setFont(). Os botes de rdio so criados, j tendo setado qual o boto que ficar selecionado inicialmente. Cada um desses botes deve ser adicionado a um grupo de botes (ButtonGroup), sendo ele responsvel pala desativao do boto anteriormente selecionado, quando um novo for clicado. No actionPerformed() verificado qual boto originou o evento, e a varivel Fonte atualizada com a fonte atual, para tambm servir de parmetro no setFont(). Isso feito atravs da criao de um objeto f, do tipo Font, incializado a partir do getFont() e passado para a varivel Fonte atravs do getName().

3.3 Bordas
O Swing oferece vrias opes de bordas para melhorar o aspecto visual da aplicao. O mtodo setBorder(), da classe JComponent, a responsvel pela definio das bordas, recebendo como parmetro um objeto de uma das classes de bordas existentes no pacote javax.swing.border. Por isso, necessrio realizar um import desse pacote. O exemplo a seguir mostra as diversas bordas existentes, permitindo a utilizao de ttulo ou no.
import java.awt.*; import java.awt.event.*; import javax.swing.*;

35

import javax.swing.border.*; public class Bordas extends JFrame implements ActionListener { private JButton RBEtched; private JButton RBEmpty; private JButton RBLine; private JButton RBMatte; private JButton RBLoweredBevel; private JButton RBRaisedBevel; private JButton RBCompound; private JCheckBox CBTitled; private Border BordaCentro = null; public Bordas() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(700,250); setTitle("Bordas"); JPanel PainelBaixo = new JPanel(); RBEtched = new JButton("Etched"); RBEmpty = new JButton("Empty"); RBLine = new JButton("Line"); RBMatte = new JButton("Matte"); RBLoweredBevel = new JButton("LoweredBevel"); RBRaisedBevel = new JButton("RaisedBevel"); RBCompound = new JButton("Compound"); CBTitled = new JCheckBox("Titled"); PainelBaixo.add(RBEtched); PainelBaixo.add(RBEmpty); PainelBaixo.add(RBLine); PainelBaixo.add(RBMatte); PainelBaixo.add(RBLoweredBevel); PainelBaixo.add(RBRaisedBevel); PainelBaixo.add(RBCompound); PainelBaixo.add(CBTitled); Border borda = BorderFactory.createEtchedBorder(); Border BordaBaixo = BorderFactory.createTitledBorder(borda," Tipos de Borda "); PainelBaixo.setBorder(BordaBaixo); Container P = getContentPane(); P.setLayout(new BorderLayout()); P.add(PainelBaixo,"South"); RBEtched.addActionListener(this); RBEmpty.addActionListener(this); RBLine.addActionListener(this); RBMatte.addActionListener(this); RBLoweredBevel.addActionListener(this); RBRaisedBevel.addActionListener(this); RBCompound.addActionListener(this); CBTitled.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource();

36

JPanel PainelCentro = new JPanel(); if (origem == RBEtched) BordaCentro = BorderFactory.createEtchedBorder(); else if (origem == RBEmpty) BordaCentro = BorderFactory.createEmptyBorder(); else if (origem == RBLine) BordaCentro = BorderFactory.createLineBorder(Color.red); else if (origem == RBMatte) BordaCentro = BorderFactory.createMatteBorder(8, 8, 8, 8, Color.orange); else if (origem == RBLoweredBevel) BordaCentro = BorderFactory.createLoweredBevelBorder(); else if (origem == RBRaisedBevel) BordaCentro = BorderFactory.createRaisedBevelBorder(); else if (origem == RBCompound) BordaCentro = BorderFactory.createCompoundBorder (BorderFactory.createEtchedBorder(), BorderFactory.createMatteBorder(3, 3, 3, 3, Color.green)); if (CBTitled.isSelected()) { Border BordaTitulo = BorderFactory.createTitledBorder(BordaCentro," Exemplo de Ttulo "); PainelCentro.setBorder(BordaTitulo); } else PainelCentro.setBorder(BordaCentro); Container P = getContentPane(); P.add(PainelCentro,"Center"); validate(); } public static void main(String[] args) { JFrame fr = new Bordas(); fr.setVisible(true); } }

Figura 3.3. Tipos de Bordas no Swing

37

A figura 3.3 mostra o resultado da execuo, onde cada um dos botes realiza a mudana para a borda especificada. O ttulo na borda somente mostrado se a caixa de seleo Titled estiver marcada. De forma geral, para criar uma borda necessrio criar um objeto Border e utilizar um dos mtodos da classe BorderFactory para criar a borda desejada. Os tipos de borda existentes, os mtodos para criao, o parmetros necessrios em cada tipo e as variaes possveis so: EtchedBorder: cria uma borda de linha com efeito 3D.
createEtchedBorder() createEtchedBorder(Color destaque, Color Sombra)

EmptyBorder: cria uma borda vazia, mas ocupa espao e permite insero de ttulo.
createEmptyBorder() createEmptyBorder(int topo, int esquerda, int base, int direita)

LineBorder: cria uma borda de linha simples.


createLineBorder(Color cor) createLineBorder(Color cor, int espessura)

MatteBorder: cria uma borda larga que pode ser preenchida com uma cor slida ou um cone.
createMatteBorder(int topo, int esquerda, int base, int direita, Color cor) createMatteBorder(int topo, int esquerda, int base, int direita, Icon icone)

BevelBorder: cria uma borda com efeito de relevo (para cima ou para baixo).
createLoweredBorder() createRaisedBorder()

CompoundBorder: cria uma borda unindo duas outras bordas.


createCompundBorder(Border BordaExterna, Border BordaInterna)

TitledBorder: cria uma borda com um ttulo. Normalmente utilizado para inserir ttulos em outras bordas.
createTitledBorder(String titulo) createTitledBorder(Border borda, String titulo) createTitledBorder(Border borda, String titulo, int alinhamento, int posicao) createTitledBorder(Border borda, String titulo, int alinhamento, int posio, Font fonte, Color cor)

O alinhamento do TitledBorder pode ser uma das constantes: TitledBorder.LEFT, TitledBorder.RIGHT ou TitledBorder.CENTER. A posio pode ser uma das constantes de TitledBorder: ABOVE_TOP, TOP, BELOW_TOP, ABOVE_BOTTOM, BOTTOM, BELOW_BOTTOM.

3.4 Caixas de Combinao


Uma caixa de combinao uma lista do tipo abre/fecha que apresenta mltiplos valores, sendo que apenas um pode ser selecionado. A classe que implementa esse componente a

38

JComboBox e o tratamento dos eventos tambm ActionListener, como mostra o exemplo a seguir. import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.border.*;

pode ser feito atravs da interface

public class CaixasDeCombinacao extends JFrame implements ActionListener { private JComboBox Cores; private Color cor = Color.green; private String Itens[] = {"Verde","Amarelo","Azul","Branco"}; private JPanel PainelSul; private JPanel PainelCentro; private Border Borda; private JLabel Texto; public CaixasDeCombinacao() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,160); setTitle("Caixa de Combinao"); Container P = getContentPane(); P.setLayout(new BorderLayout()); PainelSul = new JPanel(); Cores = new JComboBox(Itens); PainelSul.add(Cores); Cores.addActionListener(this); P.add(PainelSul,"South"); PainelCentro = new JPanel(); Borda = BorderFactory.createMatteBorder(8, 8, 8, 8, cor); PainelCentro.setBorder(Borda); Texto = new JLabel("Verde"); PainelCentro.add(Texto); P.add(PainelCentro,"Center"); } public void actionPerformed(ActionEvent evt) { JComboBox origem = (JComboBox)evt.getSource(); if ((String)origem.getSelectedItem() == "Verde") cor = Color.green; else if ((String)origem.getSelectedItem() == "Amarelo") cor = Color.yellow; else if ((String)origem.getSelectedItem() == "Azul") cor = Color.blue; else if ((String)origem.getSelectedItem() == "Branco") cor = Color.white; Borda = BorderFactory.createMatteBorder(8, 8, 8, 8, cor); PainelCentro.setBorder(Borda); Texto.setText((String)origem.getSelectedItem()); } public static void main (String[] args) {

39

CaixasDeCombinacao fr = new CaixasDeCombinacao(); fr.setVisible(true); } }

Figura 3.4. Manipulao de Bordas atravs de uma Caixa de Combinao

Uma borda Borda do tipo MatteBorder foi criada no PainelCentro para que as cores sejam alteradas a partir da seleo pela caixa de combinao Cores (figura 3.4), localizada no PainelSul. O PainelCentro tambm contm um label Texto, que mostra a cor atual da borda. Para manipular o evento de seleo da caixa de combinao, foi implementado o mtodo actionPerformed(), que define um objeto origem, do tipo JComboBox, e testa o item selecionado a partir do getSelectedItem(). Conforme a seleo, um objeto cor, do tipo Color, atualizado, para depois ser utilizado na definio da nova cor da borda. Alm disso, o label Texto tambm atualizado com a cor selecionada. Alguns outros mtodos so importantes:
void setEditable(Boolean editavel):

se o parmetro for true, o item selecionado

pode sofrer alteraes, caso contrrio no.


void addItem(Object Item):

adiciona um item lista. adiciona um item lista na posio

void insertItemAt(Object Item, int posicao):

indicada.
void removeItem(Object Item):

remove um item da lista. remove o item da lista que est

void removeItemAt(Object Item, int posicao):

posio indicada.

3.5 Continer JScrollPane e Caixas de Listagem


Sempre que se deseja incluir barras de rolagem em um componente qualquer, necessrio inserilo em um continer JScrollPane. Caso o componente inserido seja maior que o continer, automaticamente so mostradas barras de rolagem para poder visualizar a parte do componente que no ficou visvel, tanto vertical, quanto horizontalmente. No possvel atribuir um layout ao JScrollPane, pois ele tem seu prprio layout, no podendo ser alterado. Tal layout aceita apenas um componente, permitindo a insero de um outro continer, como um painel, por exemplo.

40

As caixas de listagem, criadas a partir de objetos do tipo JList, apresentam listas de valores para selees nicas ou mltiplas. Elas, por si s, no apresenta nenhuma barra de rolagem, sendo necessrio para isso, inseri-la em um continer JScrollPane, como no exemplo a seguir.
import import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.border.*; javax.swing.event.*;

public class CaixasDeListagem extends JFrame { private JList FrutasLegumes; private String NomesImagens[] = {"","Abobora.gif","Alcachofra.gif","Berinjela.gif","Maca.gif"}; private Icon Imagens[] = {new ImageIcon(NomesImagens[0]), new ImageIcon(NomesImagens[1]), new ImageIcon(NomesImagens[2]), new ImageIcon(NomesImagens[3]), new ImageIcon(NomesImagens[4])}; private String ItensLista[] = {"Nenhum","Abbora","Alcachofra","Berinjela","Ma"}; private JPanel PainelLista; private JLabel LabelImagem; public CaixasDeListagem() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(250,100); setTitle("Caixa de Listagem"); Container P = getContentPane(); PainelLista = new JPanel(); FrutasLegumes = new JList(ItensLista); FrutasLegumes.setVisibleRowCount(3); FrutasLegumes.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); PainelLista.add(new JScrollPane(FrutasLegumes)); LabelImagem = new JLabel(Imagens[0]); PainelLista.add(LabelImagem); FrutasLegumes.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { LabelImagem.setIcon(Imagens[FrutasLegumes.getSelectedIndex()]); } }); P.add(PainelLista); } public static void main (String[] args) { CaixasDeListagem fr = new CaixasDeListagem(); fr.setVisible(true); } }

41

Figura 3.5. Caixa de Listagem de seleo nica

A figura 3.5 apresenta o resultado da execuo da aplicao, onde h uma caixa de listagem com trs linhas e uma barra de rolagem. Ao clicar em cada opo, aparece ao lado a imagem solicitada. Para criar a lista foi declarado um objeto FrutasLegumes, do tipo JList, passando como parmetro um arranjo String ItensLista, com os itens desejados. A partir do mtodo setVisibleRowCount() foi definido o nmero de itens visveis da lista. O setSelectionMode() especifica o modo de seleo da lista, definido na classe ListSelectionModel, que pode ser: SINGLE_SELECTION, que permite a seleo de um nico item; SINGLE_INTERVAL_SELECTION, que permite a seleo mltipla e contgua na lista, e; MULTIPLE_INTERVAL_SELECTION, que permite a seleo mltipla, no interessando quais itens sero selecionados. Para que a lista pudesse ser apresentada com a barra de rolagem, o objeto FrutasLegumes foi adicionado a um JScrollPane que, por sua vez, foi adicionado ao painel. Por fim, para ser possvel tratar o evento de seleo na lista, foi necessrio implementar a interface ListSelectionListener(), que est definida em javax.swing.event, sendo preciso importar esse pacote, e que utiliza o mtodo valueChanged() para efetuar as aes desejadas. Para alterar a imagem do LabelImagem foi utilizado o setIcon(), relacionando o ndice do arranjo Imagens com o ndice do item que foi selecionado na lista, buscado atravs do getSelectedIndex(). O modo como o evento foi tratado poderia ter sido feito como nos exemplos vistos at agora, assim: Antes de tudo, inserir o implements ListSelectionListener na criao da classe:
public class CaixasDeListagem extends JFrame implements ListSelectionListener

Depois, indicar o prprio frame como objeto ouvinte:


FrutasLegumes.addListSelectionListener(this);

Por fim, implementar o mtodo valueChanged():


public void valueChanged(ListSelectionEvent evt) { LabelImagem.setIcon(Imagens[FrutasLegumes.getSelectedIndex()]); }

Para que se possa efetuar a seleo mltipla dos itens de uma caixa de listagem, necessrio determinar se a seleo SINGLE_INTERVAL_SELECTION, permitindo selecionar um intervalo contguo, clicando com o mouse em um primeiro item e, com a tecla Shift pressionada, clicando no ltimo item desejado; ou MULTIPLE_INTERVAL_SELECTION, permitindo selecionar itens no contguos, atravs da utilizao da tecla Ctrl, clicando com o mouse nos itens desejados. Exemplo:
import java.awt.*; import java.awt.event.*; import javax.swing.*;

42

import javax.swing.event.*; public class ListaSelecaoMultipla extends JFrame { private JList Numeros; private JList Selecionados; private String ItensLista[] = {"Zero","Um","Dois","Trs","Quatro","Cinco","Seis","Sete"}; private JPanel PainelListaSM; public ListaSelecaoMultipla() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(250,150); setTitle("Seleo Mltipla"); Container P = getContentPane(); PainelListaSM = new JPanel(); Numeros = new JList(ItensLista); Numeros.setVisibleRowCount(5); Numeros.setFixedCellWidth(60); Numeros.setFixedCellHeight(20); Numeros.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); PainelListaSM.add(new JScrollPane(Numeros)); Selecionados = new JList(); Selecionados.setVisibleRowCount(5); Selecionados.setFixedCellWidth(80); Selecionados.setFixedCellHeight(20); Selecionados.setSelectionMode (ListSelectionModel.SINGLE_INTERVAL_SELECTION); PainelListaSM.add(new JScrollPane(Selecionados)); P.add(PainelListaSM); Numeros.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { Selecionados.setListData(Numeros.getSelectedValues()); } }); } public static void main (String[] args) { ListaSelecaoMultipla fr = new ListaSelecaoMultipla(); fr.setVisible(true); } }

43

Figura 3.6. Caixas de Listagem de seleo mltipla

Na figura 3.6 possvel perceber os vrios itens selecionados intercaladamente na primeira caixa de listagem. A segunda caixa foi criada para mostrar os itens selecionados na primeira caixa. Dois novos mtodos foram utilizados para alterar a parte visual das caixas de listagem: setFixedCellWidth(), que determina um tamanho fixo de largura da caixa de listagem e; setFixedCellHeight(), que determina um tamanho fixo de algura da caixa. Percebe-se que a primeira caixa de listagem permite uma seleo intercalada de valores, atravs da utilizao da tecla Ctrl (MULTIPLE_INTERVAL_SELECTION), enquanto a segunda caixa permite apenas a seleo contgua, utilizando a tecla Shift (SINGLE_INTERVAL_SELECTION). A caixa de listagem Numeros recebeu um ouvinte de eventos que, no momento que cada item selecionado, realiza a operao de atualizao da caixa Selecionados. Isso feito atravs do mtodo setListData(), que recebe como parmetro o conjunto de valores selecionados a partir do mtodo getSelectedValues().

3.6 Dividindo Painis


A classe JSplitPane a responsvel pela diviso de reas. Na verdade, ele um continer especial que permite o compartilhamento do espao para dois outros componentes, separando-os por uma barra divisora ajustvel. O exemplo a seguir mostra dois labels com imagens compartilhando a rea definida pelo JSplitPane.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PainelDividido extends JFrame { public PainelDividido() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(615,300); setTitle("Painel Dividido"); JLabel Um = new JLabel(new ImageIcon("Um.jpg")); JLabel Dois = new JLabel(new ImageIcon("Dois.jpg")); Component Esquerda = new JScrollPane(Um); Component Direita = new JScrollPane(Dois); JSplitPane Divisao = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, Esquerda, Direita); Divisao.setDividerLocation(300); Divisao.setDividerSize(10); Container P = getContentPane(); P.add(Divisao); } public static void main (String[] args) { PainelDividido fr = new PainelDividido(); fr.setVisible(true); } }

44

Figura 3.7. Labels com imagens compartilhando um painel dividido pelo JSplitPane

A barra que divide as imagens (figura 3.7) redimensionvel, permitindo aumentar ou diminuir o espao de cada um dos componentes. Depois de criados os labels Um e Dois, eles so colocados em um JScrollPane, para que tenham barras de rolagem, e atribudos a dois objetos Esquerda e Direita, do tipo Component. Estes, por sua vez, so os componentes que vo compartilhar a diviso horizontal (HORIZONTAL_SPLIT) feita pelo JSplitPane. A outra forma de diviso a VERTICAL_SPLIT, que divide o painel verticalmente. O mtodo setDividerLocation() indica a posio onde deve ficar o divisor redimensionvel e o mtodo setDividerSize() determina o tamanho em pixels da barra divisria.

3.8 Barra de Controle Deslizante


A partir de um objeto do tipo JSlider possvel selecionar um valor inteiro entre um intervalo definido em uma barra de controle com um marcador de medidas. Tal componente possui diversas configuraes possveis, como: o posicionamento horizontal ou vertical, a exibio de marcas de medida principais e secundrias e a mostragem de rtulos para essas marcas. O exemplo a seguir mostra uma barra de controle deslizante (JSlider) e uma barra de rolagem normal (JScrollBar).
import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

public class ControleDeslizante extends JFrame { private JSlider TamanhoTextoSlider; private JScrollBar TamanhoTextoScroll; private JLabel TextoSlider; private JLabel TextoScroll; public ControleDeslizante()

45

{ addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(570,230); setTitle("Controle Deslizante"); Container P = getContentPane(); P.setLayout(new BorderLayout()); JPanel PainelCDNorte = new JPanel(); TextoSlider = new JLabel("JSlider tamanho 20"); TextoSlider.setFont(new Font("SansSerif",Font.PLAIN,20)); PainelCDNorte.add(TextoSlider); P.add(PainelCDNorte,"North"); JPanel PainelCDCentro = new JPanel(); TextoScroll = new JLabel("JScrollBar tamanho 20"); TextoScroll.setFont(new Font("SansSerif",Font.PLAIN,20)); PainelCDCentro.add(TextoScroll); P.add(PainelCDCentro,"Center"); JPanel PainelCDSul = new JPanel(); TamanhoTextoSlider = new JSlider(SwingConstants.HORIZONTAL,0,50,20); TamanhoTextoSlider.setMajorTickSpacing(10); TamanhoTextoSlider.setMinorTickSpacing(2); TamanhoTextoSlider.setPaintTicks(true); PainelCDSul.add(TamanhoTextoSlider); TamanhoTextoScroll = new JScrollBar(JScrollBar.HORIZONTAL,20,0,0,50); TamanhoTextoScroll.setPreferredSize( new Dimension(200,TamanhoTextoScroll.getPreferredSize().height)); PainelCDSul.add(TamanhoTextoScroll); P.add(PainelCDSul,"South"); TamanhoTextoSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { TextoSlider.setText("JSlider tamanho "+TamanhoTextoSlider.getValue()); TextoSlider.setFont( new Font("SansSerif",Font.PLAIN,TamanhoTextoSlider.getValue())); } }); TamanhoTextoScroll.addAdjustmentListener(new AdjustmentListener() { public void adjustmentValueChanged(AdjustmentEvent e) { TextoScroll.setText( "JScrollBar tamanho "+TamanhoTextoScroll.getValue()); TextoScroll.setFont( new Font("SansSerif",Font.PLAIN,TamanhoTextoScroll.getValue())); } }); } public static void main (String[] args) { ControleDeslizante fr = new ControleDeslizante(); fr.setVisible(true); } }

46

Figura 3.8. Utilizao do JSlider e e JScrollBar para alterar tamanho de fonte

Dois labels de tamanho 20 foram inseridos em dois painis (PainelCDNorte e PainelCDCentro) para mostrar a funcionalidade dos componentes (figura 3.8). No PainelCDSul foi inserido um componente TamanhoTextoSlider, do tipo JSlider, para controlar o tamanho do primeiro label, e um outro componente TamanhoTextoScroll, para controlar o tamanho do segundo label. Para criar o objeto JSlider foi identificada a orientao como sendo horizontal (SwingConstants.HORIZONTAL), o valor mnimo como sendo 0, o valor mximo como sendo 50, e a posio de incio como sendo 20. Aps, foram setados os marcadores principal e secundrio como sendo 10 e 2, atravs do setMajorTickSpacing() e do setMinorTickSpacing(), para depois serem mostrados atravs do setPaintTicks(). Para criar o objeto JScrollBar tambm foi identificada a orientao como sendo horizontal (JScrollBar.HORIZONTAL), a posio de incio como sendo 20, a rea visvel da barra de rolagem como sendo 0 pois, nesse tipo de utilizao do JScrollBar, necessria a utilizao total da barra, o valor mnimo como sendo 0 e o valor mximo como sendo 50. O seu tamanho foi definido pelo mtodo setPreferredSize(), que necessita de um objeto Dimension como parmetro, sendo passado os valores de largura 200 e sendo mantida a altura original da barra de rolagem, atravs do getPreferredSize().height. Para o tratamento dos eventos do objeto TamanhoTextoSlider foi feita a implementao do mtodo stateChanged(), a partir da interface ChangeListener, onde, a cada modificao no controle deslizante, o texto alterado pelo setText() e a fonte alterada pelo setFont(), passando como parmetro a posio atual do controle deslizante, a partir do getValue(). A mesma coisa ocorre no tratamento dos eventos do objeto TamanhoTextoScroll, utilizando uma interface diferente, a AdjustmentListener, com a implementao do mtodo adjustmentValueChanged().

3.8 Abas Rotuladas e Caixas de Dilogo


Na construo de aplicaes, freqentemente ocorre o problema de falta de espao para inserir todos os componentes necessrios. Uma opo muito utilizada nesses casos a criao de abas rotuladas conforme o tipo de objetos que sero inseridos. A classe que realiza essa tarefa a JTabbedPane, que nada mais que um continer que permite a insero de diversos painis, um em cada aba. Para exemplificar a utilizao das abas rotuladas, o exemplo a seguir possui seis

47

abas, cada uma com um tipo diferente de caixa de dilogo, provenientes de objetos das classes JOptionPane, JFileChooser e JColorChooser. As caixas de dilogo so, por padro, modais, ou seja, no possvel interagir com outras janelas enquanto essa no for fechada. Elas so utilizadas para exibir alguma mensagem ou obter algum tipo de informao do usurio, seja uma confirmao, uma entrada de dados, ou uma seleo de algo.
import import import import java.awt.*; java.awt.event.*; javax.swing.*; java.io.*;

public class AbasRotuladas extends JFrame implements ActionListener { private JTabbedPane Abas; private JButton CDMensagem1; private JButton CDMensagem2; private JButton CDMensagem3; private JButton CDConfirmacao1; private JButton CDConfirmacao2; private JButton CDConfirmacao3; private JButton CDConfirmacao4; private JLabel LabelConfirmacao; private JButton CDOpcao1; private JLabel LabelOpcao; private JButton CDEntrada1; private JButton CDEntrada2; private JButton CDEntrada3; private JLabel LabelEntrada; private JButton CDArquivo1; private JLabel LabelArquivo1; private JLabel LabelArquivo2; private JButton CDCor1; private JLabel LabelCor; public AbasRotuladas() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(450,150); setLocation(300,200); setTitle("Caixas de Dilogo de..."); Container P = getContentPane(); Abas = new JTabbedPane(); JPanel PCxDlgMensagem = new JPanel(); CDMensagem1 = new JButton("Mensagem 1"); CDMensagem2 = new JButton("Mensagem 2"); CDMensagem3 = new JButton("Mensagem 3"); PCxDlgMensagem.add(CDMensagem1); PCxDlgMensagem.add(CDMensagem2); PCxDlgMensagem.add(CDMensagem3); JPanel PCxDlgConfirmacao = new JPanel(); CDConfirmacao1 = new JButton("Confirmao 1"); CDConfirmacao2 = new JButton("Confirmao 2"); CDConfirmacao3 = new JButton("Confirmao 3"); CDConfirmacao4 = new JButton("Confirmao 4"); LabelConfirmacao = new JLabel("Retorno:");

48

PCxDlgConfirmacao.add(CDConfirmacao1); PCxDlgConfirmacao.add(CDConfirmacao2); PCxDlgConfirmacao.add(CDConfirmacao3); PCxDlgConfirmacao.add(CDConfirmacao4); PCxDlgConfirmacao.add(LabelConfirmacao); JPanel PCxDlgOpcao = new JPanel(); CDOpcao1 = new JButton("Opo 1"); LabelOpcao = new JLabel("Retorno:"); PCxDlgOpcao.add(CDOpcao1); PCxDlgOpcao.add(LabelOpcao); JPanel PCxDlgEntrada = new JPanel(); CDEntrada1 = new JButton("Entrada 1"); CDEntrada2 = new JButton("Entrada 2"); CDEntrada3 = new JButton("Entrada 3"); LabelEntrada = new JLabel("Retorno:"); PCxDlgEntrada.add(CDEntrada1); PCxDlgEntrada.add(CDEntrada2); PCxDlgEntrada.add(CDEntrada3); PCxDlgEntrada.add(LabelEntrada); JPanel PCxDlgArquivo = new JPanel(); CDArquivo1 = new JButton("Arquivo 1"); LabelArquivo1 = new JLabel("Retorno:"); LabelArquivo2 = new JLabel("Seleo:"); PCxDlgArquivo.add(CDArquivo1); PCxDlgArquivo.add(LabelArquivo1); PCxDlgArquivo.add(LabelArquivo2); JPanel PCxDlgCor = new JPanel(); CDCor1 = new JButton("Cor 1"); LabelCor = new JLabel("Retorno:"); PCxDlgCor.add(CDCor1); PCxDlgCor.add(LabelCor); Abas.addTab("Mensagem",PCxDlgMensagem); Abas.addTab("Confirmao",PCxDlgConfirmacao); Abas.addTab("Opo",PCxDlgOpcao); Abas.addTab("Entrada",PCxDlgEntrada); Abas.addTab("Arquivo",PCxDlgArquivo); Abas.addTab("Cor",PCxDlgCor); P.add(Abas); CDMensagem1.addActionListener(this); CDMensagem2.addActionListener(this); CDMensagem3.addActionListener(this); CDConfirmacao1.addActionListener(this); CDConfirmacao2.addActionListener(this); CDConfirmacao3.addActionListener(this); CDConfirmacao4.addActionListener(this); CDOpcao1.addActionListener(this); CDEntrada1.addActionListener(this); CDEntrada2.addActionListener(this); CDEntrada3.addActionListener(this); CDArquivo1.addActionListener(this); CDCor1.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); int retorno = 0;

49

String valorRet = null; Icon icone = new ImageIcon("LogoSun.gif"); if (origem == CDMensagem1) JOptionPane.showMessageDialog(null, "Esta uma caixa de dilogo de Mensagem"); else if (origem == CDMensagem2) JOptionPane.showMessageDialog(null, "Esta uma caixa de dilogo de Mensagem", "Mensagem", JOptionPane.WARNING_MESSAGE); else if (origem == CDMensagem3) JOptionPane.showMessageDialog(null, "Esta uma caixa de dilogo de Mensagem", "Mensagem", JOptionPane.WARNING_MESSAGE, icone); else if (origem == CDConfirmacao1) { retorno = JOptionPane.showConfirmDialog(null,"Confirma Operao?"); LabelConfirmacao.setText("Retorno: " + retorno); } else if (origem == CDConfirmacao2) { retorno = JOptionPane.showConfirmDialog(null,"Confirma Operao?", "Confirmao", JOptionPane.YES_NO_OPTION); LabelConfirmacao.setText("Retorno: " + retorno); } else if (origem == CDConfirmacao3) { retorno = JOptionPane.showConfirmDialog(null,"Confirma Operao?", "Confirmao", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); LabelConfirmacao.setText("Retorno: " + retorno); } else if (origem == CDConfirmacao4) { retorno = JOptionPane.showConfirmDialog(null,"Confirma Operao?", "Confirmao", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, icone); LabelConfirmacao.setText("Retorno: " + retorno); } else if (origem == CDOpcao1) { Object[] opcoes = { "OK", "Cancelar" }; retorno = JOptionPane.showOptionDialog(null, "Esta uma caixa de dilogo de Opo", "Opo",JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, opcoes, opcoes[0]); LabelOpcao.setText("Retorno: " + retorno); } else if (origem == CDEntrada1) { valorRet = JOptionPane.showInputDialog(null, "Digite um valor"); LabelEntrada.setText("Retorno: " + valorRet); } else if (origem == CDEntrada2) { valorRet = JOptionPane.showInputDialog(null, "Digite um valor", "Entrada", JOptionPane.QUESTION_MESSAGE); LabelEntrada.setText("Retorno: " + valorRet);

50

} else if (origem == CDEntrada3) { Object[] valores= {"Opo Um","Opo Dois","Opo Trs","Opo Quatro"}; Object valorSelec = JOptionPane.showInputDialog(null, "Escolha uma opo", "Entrada", JOptionPane.INFORMATION_MESSAGE, null, valores, valores[0]); LabelEntrada.setText("Retorno: " + valorSelec.toString()); } else if (origem == CDArquivo1) { JFileChooser abreArquivo = new JFileChooser(); abreArquivo.setCurrentDirectory(new File(".")); abreArquivo.setSelectedFile(new File("AbasRotuladas.java")); retorno = abreArquivo.showOpenDialog(this); LabelArquivo1.setText("Retorno: " + retorno); if (retorno == JFileChooser.APPROVE_OPTION) { File arquivoSelec = abreArquivo.getSelectedFile(); LabelArquivo2.setText("Seleo: " + arquivoSelec.getName()); } else LabelArquivo2.setText("Seleo: Nenhum arquivo"); } else if (origem == CDCor1) { JColorChooser abreCor = new JColorChooser(); Color c = abreCor.showDialog(this, "Escolha uma cor", Color.black); LabelCor.setForeground(c); LabelCor.setText("Retorno: " + c.toString()); } } public static void main (String[] args) { AbasRotuladas fr = new AbasRotuladas(); fr.setVisible(true); } }

Figura 3.9. Abas rotuladas para demonstrao das diversas caixas de dilogo

Na figura 3.9 possvel visualizar a situao do frame na execuo da aplicao. Para que as abas fossem criadas, foi definido um objeto Abas, do tipo JTabbedPane. Como so seis as abas, foram criados seis painis (PCxDlgMensagem, PCxDlgConfirmacao, PCxDlgOpcao, PCxDlgEntrada,

51

e PCxDlgCor), inseridos botes e labels em cada um deles, conforme a necessidade, para depois, atravs do mtodo addTab(), inseri-los no objeto Abas, permitindo a incluso de um ttulo para cada aba.
PCxDlgArquivo

Figura 3.10. Caixas de dilogo de mensagem, confirmao, opo e entrada

As primeiras quatro abas correspondem s caixas de dilogo existentes na classe JOptionPane, dividas em quatro tipos, mostrados nos exemplos da figura 3.10. O primeiro tipo a caixa de dilogo de mensagem, onde uma mensagem mostrada, acompanhada de um boto OK. O mtodo para criao desse tipo de caixa de dilogo o showMessageDialog() e existem variaes em relao aos parmetros que so passados, que so:
static void showMessageDialog(Component componentePai, Object mensagem): mostra uma caixa de mensagem com o ttulo Message e um boto OK. static void showMessageDialog(Component componentePai, Object mensagem, String titulo, int tipoDaMensagem): mostra uma caixa de mensagem com o ttulo definido por titulo, um boto OK e o tipo da mensagem, que identifica o cone apresentado, podendo ser ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, ou PLAIN_MESSAGE. static void showMessageDialog(Component componentePai, Object mensagem, String titulo, int tipoDaMensagem, Icon icone): idntico ao anterior, com a

possibilidade de mostrar um cone especfico. O segundo tipo a caixa de dilogo de confirmao, onde uma mensagem mostrada, normalmente uma pergunta, acompanhada de botes de confirmao. O mtodo para criao desse tipo de caixa de dilogo o showConfirmDialog(), que possui como retorno um inteiro que indica o boto que foi pressionado (comeando por zero). No exemplo, tal retorno armazenado em uma varivel retorno e mostrado no label LabelConfirmacao. Tambm existem variaes em relao aos parmetros que so passados:

52

static int showConfirmDialog(Component componentePai, Object mensagem): mostra uma caixa de confirmao com o ttulo Select an Option e os botes Yes, No e Cancel. static int showConfirmDialog(Component componentePai, Object message, String titulo, int tipoDaOpcao): mostra uma caixa de confirmao com o ttulo definido por titulo, e o o conjunto de botes definido por tipoDaOpcao, que pode ser YES_NO_OPTION, ou YES_NO_CANCEL_OPTION. static int showConfirmDialog(Component componentePai, Object message, String titulo, int tipoDaOpcao, int tipoDaMensagem): idntico ao anterior, com a possibilidade de identificar o tipo da mensagem e o cone, podendo ser ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, ou PLAIN_MESSAGE. static int showConfirmDialog(Component componentePai, Object message, String titulo, int tipoDaOpcao, int tipoDaMensagem, Icon icone): idntico

ao anterior, permitindo mostrar um cone. O terceiro tipo a caixa de dilogo de opo, onde possvel determinar as opes possveis para os botes, na resposta de uma mensagem. O mtodo para criao desse tipo de caixa de dilogo o showOptionDialog(), que possui como retorno um inteiro que indica o boto que foi pressionado (comeando por zero). Nesse tipo de caixa de dilogo no existem variaes em relao aos parmetros, sendo necessrio passar todos eles. Ento, a nica sintaxe aceita :
static int showOptionDialog(Component componentePai, Object mensagem, String titulo, int tipoDaOpcao, int tipoDaMensagem, Icon icone, Object[] opcoes, Object valorInicial): mostra uma caixa de opo com o ttulo definido por titulo, uma mensagem, a escolha do conjunto de botes utilizado, definido por tipoDaOpcao, que pode ser YES_NO_OPTION, ou YES_NO_CANCEL_OPTION, o tipo da mensagem, que identifica o cone apresentado, podendo ser ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, ou PLAIN_MESSAGE, um cone, o nome dos botes, definido por um objeto opcoes, do tipo Object, e o boto que ser o inicialmente selecionado, definido por valorInicial.

O quarto tipo a caixa de dilogo de entrada, que um pouco diferente que as outras, pois permite a insero ou seleo de valores textuais. Se a caixa de dilogo permitir a insero de um valor, o retorno do tipo String, j que o que vai ser digitado um texto. No caso de ser permitida a seleo de um dos valores em uma lista, o retorno um objeto do tipo Object, onde, atravs de um mtodo toString() possvel obter o contedo textual do tem selecionado. O mtodo para criao desse tipo de caixa de dilogo o showInputDialog() e suas variaes so:
static String showInputDialog(Component componentePai, Object mensagem): mostra uma caixa de entrada com com o ttulo Input, uma caixa de texto para a entrada de dados e os botes OK e Cancel. static String showInputDialog(Component componentePai, Object mensagem, String titulo, int tipoDaMensagem): mostra uma caixa de entrada como a anterior,

53

com a possibilidade de inserir um ttulo e selecionar o tipo da mensagem, que vai definir o cone a ser apresentado, que pode ser: ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, ou PLAIN_MESSAGE.
static Object showInputDialog(Component componentePai, Object mensagem, String titulo, int tipoDaMensagem, Icon icone, Object[] valoresSelec, Object valorSelecInicial): tem as mesmas opes que o anterior, porm, permite inserir um cone e, atravs da criao de um objeto do tipo Object, apresenta os valores em uma lista, podendo ainda ter o valor inicial setado por valorSelecInicial.

Figura 3.11. Caixa de dilogo de seleo de arquivos

A quinta aba apresenta um boto que, ao ser clicado, abre uma caixa de dilogo de arquivos, como mostra a figura 3.11. A classe JFileChooser fornece mtodos para apresentar essa caixa de dilogo e configur-la conforme as necessidades. Semelhante s outras caixas de dilogo, essa tambm apresentada na forma modal, tendo que fecha-la antes de continuar a utilizao da aplicao que a chamou. No exemplo apresentado criado um objeto abreArquivo, do tipo JFileChooser, em primeiro lugar. Aps setado o diretrio a ser mostrado inicialmente, atravs do mtodo setCurrentDirectory(), passando como parmetro um objeto do tipo File. Alm do diretrio, foi setado o nome do arquivo inicial da busca, atravs do mtodo setSelectedFile(), que tambm precisa de um objeto do tipo File como parmetro. No foi utilizado no exemplo, mas, se for necessrio permitir a seleo mltipla de arquivos, possvel utilizar o mtodo setMultiSelectionEnabled(true). Para abrir a caixa de dilogo, basta chamar o mtodo showOpenDialog(), tendo como valor de retorno um inteiro que representa o boto que foi pressionado (0 para Open e 1 para Cancel). Da mesma forma, se for desejvel abrir uma caixa de dilogo para Salvar arquivo, ao invs de Abrir, basta utilizar o showSaveDialog(). No exemplo, foi utilizada a varivel retorno para ser posteriormente mostrada no label LabelArquivo1.

54

Esse retorno pode ser testado utilizando o JFileChooser.APPROVE_OPTION, no caso de ter sido clicado o boto Open e JFileChooser.CANCEL_OPTION, no caso de ter sido clicado o boto Cancel. No exemplo, se for clicado no boto Open, atribudo ao objeto arquivoSelec, do tipo File, o retorno do mtodo getSelectedFile(), que traz o arquivo que foi selecionado na caixa de dilogo. Se existir a situao de mltipla seleo de arquivos, o mtodo a ser utilizado o getSelectedFiles(), que retorna um arranjo de objetos do tipo File. Aps, o nome desse arquivo foi mostrado no label LabelArquivo2, atravs do mtodo getName(). Caso tenha sido clicado no boto Cancel, esse mesmo label apresenta uma mensagem que no foi selecionado nenhum arquivo.

Figura 3.12. Caixa de dilogo de seleo de cores

A sexta e ltima aba apresenta um boto que, ao ser clicado, abre uma caixa de dilogo de seleo de cores, mostrado na figura 3.12. A classe JColorChooser a responsvel por essa tarefa. No exemplo, foi criado um objeto abreCor a partir dessa classe e depois foi aberta a caixa de dilogo a partir do mtodo showDialog(), tendo que passar como parmetro o seu ttulo e a sua cor inicial. O retorno desse mtodo foi atribudo a um objeto c, do tipo Color, para depois ser utilizado na determinao da cor do label, atravs do mtodo setForeground().

3.9 Menus e reas de Texto


O Swing apresenta suporte a menus a partir das classes JMenuBar, JMenu, JMenuItem, JCheckBoxMenuItem e JRadioButtonMenuItem. Para criar um menu no necessrio ter um gerenciador de layout especfico, sendo normalmente inserido no prprio frame. A barra de menu apresentada, normalmente, no topo do frame, com os nomes para cada menu suspenso que, ao 55

serem clicados, podem abrir itens de menu, com aes diretas, ou submenus, que abrem outros menus suspensos direita, contendo itens de menu ou at mesmo outros submenus. Os itens de menu podem ser mostrados de diversas formas: com uma imagem associada, com teclas de atalho, com teclas aceleradoras, na forma de caixa de seleo ou boto de rdio. Ao serem clicados, os itens de menu disparam eventos de ao, como um boto, por exemplo. Referente s teclas de atalho, so utilizados mnemnicos para realizar essa funo, que sublinham um caracter para cada item de menu e so ativados utilizando a tecla Alt + caracter sublinhado. Quanto s teclas aceleradoras, possvel relacionar uma combinao de teclas, ou uma tecla de funo, aos itens de menu, como Ctrl + C, Alt + R ou F3. Para demonstar a utilizao da maioria das funes possveis em um menu, o exemplo a seguir apresenta uma barra de menu com itens que manipulam uma rea de texto. Uma rea de texto semelhante aos objetos da classe JTextField, mas permite a entrada de mais que uma linha de texto, podendo utilizar a tecla Enter para passar de uma linha para outra. A classe responsvel por esse componente a JTextArea, permitindo especificar o nmero de linhas e colunas na criao dos seus objetos.
import javax.swing.*; import java.awt.event.*; import java.awt.*; public class TesteDeMenu extends JFrame implements ActionListener { private JRadioButtonMenuItem RBFontes[],RBCores[]; private JCheckBoxMenuItem CBNegritoItalico[]; private Color cores[]= {Color.black, Color.red, Color.blue, Color.orange, Color.green}; private JTextArea AreaTexto; private ButtonGroup grupoFontes, grupoCores; public TesteDeMenu() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(400,180); setLocation(200,150); setTitle("Menus e reas de Texto"); JMenuBar BarraMenu = new JMenuBar(); setJMenuBar(BarraMenu); // criao do menu Arquivo JMenu menuArquivo = new JMenu("Arquivo"); menuArquivo.setMnemonic('A'); JMenuItem itemNovo = new JMenuItem("Novo...", new ImageIcon("novo.gif")); itemNovo.setMnemonic('N'); JMenuItem itemAbrir= new JMenuItem("Abrir...",new ImageIcon("abrir.gif")); itemAbrir.setMnemonic('b'); itemAbrir.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));; JMenuItem itemSalvar= new JMenuItem("Salvar",new ImageIcon("salvar.gif")); itemSalvar.setMnemonic('S'); itemSalvar.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));; JMenuItem itemSair= new JMenuItem("Sair");

56

itemSair.setMnemonic('r'); itemSair.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK));; menuArquivo.add(itemNovo); menuArquivo.add(itemAbrir); menuArquivo.addSeparator(); menuArquivo.add(itemSalvar); menuArquivo.addSeparator(); menuArquivo.add(itemSair); BarraMenu.add(menuArquivo); itemNovo.addActionListener(this); itemAbrir.addActionListener(this); itemSalvar.addActionListener(this); itemSair.addActionListener(this); // criao do menu Editar JMenu menuEditar = new JMenu("Editar"); menuEditar.setMnemonic('E'); JMenuItem itemRecortar = new JMenuItem("Recortar...", new ImageIcon("recortar.gif")); itemRecortar.setMnemonic('t'); itemRecortar.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));; JMenuItem itemCopiar = new JMenuItem("Copiar...", new ImageIcon("copiar.gif")); itemCopiar.setMnemonic('b'); itemCopiar.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));; JMenuItem itemColar = new JMenuItem("Colar...", new ImageIcon("colar.gif")); itemColar.setMnemonic('S'); itemColar.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));; menuEditar.add(itemRecortar); menuEditar.add(itemCopiar); menuEditar.add(itemColar); BarraMenu.add(menuEditar); itemRecortar.addActionListener(this); itemCopiar.addActionListener(this); itemColar.addActionListener(this); // criao do menu Formatar JMenu menuFormatar = new JMenu("Formatar"); menuFormatar.setMnemonic('F'); // criao do submenu Cor String nomesCores[]= {"Preto", "Vermelho", "Azul", "Laranjado", "Verde"}; JMenu menuCor = new JMenu("Cor"); menuCor.setMnemonic('C'); RBCores = new JRadioButtonMenuItem[nomesCores.length]; grupoCores = new ButtonGroup(); for (int i = 0; i < nomesCores.length; i++) { RBCores[i] = new JRadioButtonMenuItem(nomesCores[i]); menuCor.add(RBCores[i]); grupoCores.add(RBCores[i]); RBCores[i].addActionListener(this); } RBCores[0].setSelected(true); menuFormatar.add(menuCor);

57

menuFormatar.addSeparator(); // criao do submenu Fonte String nomesFontes[] = {"SansSerif", "Monospaced", "Serif"}; JMenu menuFonte = new JMenu("Fonte"); menuFonte.setMnemonic('n'); RBFontes = new JRadioButtonMenuItem[nomesFontes.length]; grupoFontes = new ButtonGroup(); for (int i = 0; i < RBFontes.length; i++) { RBFontes[i] = new JRadioButtonMenuItem(nomesFontes[i]); menuFonte.add(RBFontes[i]); grupoFontes.add(RBFontes[i]); RBFontes[i].addActionListener(this); } RBFontes[0].setSelected(true); menuFonte.addSeparator(); String CBItalicoNegrigoItens[] = {"Negrito", "Itlico"}; CBNegritoItalico = new JCheckBoxMenuItem[CBItalicoNegrigoItens.length]; for (int i = 0; i < CBItalicoNegrigoItens.length; i++) { CBNegritoItalico[i] = new JCheckBoxMenuItem(CBItalicoNegrigoItens[i]); menuFonte.add(CBNegritoItalico[i]); CBNegritoItalico[i].addActionListener(this); } menuFormatar.add(menuFonte); BarraMenu.add(menuFormatar); // criao do menu Ajuda JMenu menuAjuda = new JMenu("Ajuda"); menuAjuda.setMnemonic('u'); JMenuItem itemSobre = new JMenuItem("Sobre a Aplicao..."); itemSobre.setMnemonic('S'); menuAjuda.add(itemSobre); BarraMenu.add(menuAjuda); itemSobre.addActionListener(this); AreaTexto = new JTextArea(5, 40); AreaTexto.setForeground(Color.black); AreaTexto.setFont(new Font("SansSerif", Font.PLAIN, 14)); AreaTexto.setLineWrap(true); Container P = getContentPane(); P.add(new JScrollPane(AreaTexto)); } public void actionPerformed(ActionEvent evt) { if (evt.getSource() instanceof JMenuItem) { String item = evt.getActionCommand(); if (item == "Novo...") JOptionPane.showMessageDialog(this, "Opao Novo no disponvel!", "Alerta", JOptionPane.WARNING_MESSAGE); else if (item == "Abrir...") JOptionPane.showMessageDialog(this, "Opao Abrir no disponvel!", "Alerta", JOptionPane.WARNING_MESSAGE); else if (item == "Salvar") JOptionPane.showMessageDialog(this, "Opao Salvar no disponvel!", "Alerta", JOptionPane.WARNING_MESSAGE); else if (item == "Sair")

58

System.exit(0); else if (item == "Recortar...") AreaTexto.cut(); else if (item == "Copiar...") AreaTexto.copy(); else if (item == "Colar...") AreaTexto.paste(); else if (item == "Sobre a Aplicao...") JOptionPane.showMessageDialog(this, "Este um exemplo de utilizao de menus", "Sobre", JOptionPane.PLAIN_MESSAGE); else { int Tipo = Font.PLAIN; if (CBNegritoItalico[0].isSelected()) Tipo += Font.BOLD; if (CBNegritoItalico[1].isSelected() ) Tipo += Font.ITALIC; AreaTexto.setFont(new Font(AreaTexto.getFont().getName(), Tipo, 14)); for (int i = 0; i < RBCores.length; i++) if (evt.getSource() == RBCores[i]) { AreaTexto.setForeground(cores[i]); break; } for (int i = 0; i < RBFontes.length; i++ ) if (evt.getSource() == RBFontes[i]) { AreaTexto.setFont(new Font(RBFontes[i].getText(), Tipo, 14)); break; } repaint(); } } } public static void main(String args[]) { TesteDeMenu fr = new TesteDeMenu(); fr.setVisible(true); } }

Figura 3.13. Manipulao de uma rea de texto a partir de menus

59

A figura 3.13 mostra a execuo da aplicao, notando que no foi inserido nenhum painel no frame, tendo sido setada a barra de menu para o frame e inserida a rea de texto diretamente em um continer. Para criar uma rea de texto necessrio, primeiramente, criar um objeto do tipo JTextArea e passar os parmetros para determinar o nmero de linhas e o nmero de colunas desejado. Aps, alguns mtodos podem ser utilizados para configurar a rea: o setForeground() indica a cor do texto; o setFont() determina o tipo, tamanho e formato de fonte; o setLineWrap() determina se o texto vai mudar de linha ao chegar no final da rea definida. Para que o texto possa ser mostrado com barras de rolagem, caso este seja maior que a rea visvel, necessrio inserir o objeto rea de texto em um objeto JScrollPane e aps inseri-lo no continer. Dois outros mtodos so teis: o setWrapStyleWord(), que faz a quebra da linha ao final da palavra se o parmetro for true, ou ignora o final da palavra para a quebra da linha, se o parmetro for falso, e; o setTabSize(), que determina, em seu parmetro, o nmero de colunas utilizados para a tabulao.

Figura 3.14. As opes existentes no menu

Para criar o menu mostrado na figura 3.14, foi necessrio seguir vrios passos. No exemplo, antes de tudo, foi criado o objeto BarraMenu, do tipo JMenuBar, para depois ser passado como parmetro pelo mtodo setJMenuBar(), que responsvel pela insero do menu no frame. Aps foram inseridos os vrios menus que compem a barra de menu. Para a criao do menu Arquivo foi criado um objeto menuArquivo, do tipo JMenu e setado um mnemnico, que ir sublinhar o caracter desejado e servir de tecla de atalho, atravs do mtodo setMnemonic(). Os itens de menu so adicionados a seguir, a partir da criao de objetos do tipo JMenuItem, permitindo a definio de imagens a serem mostradas juntamente com os itens. Para cada item foi setada uma tecla de atalho a partir do setMnemonic() e, para alguns deles, foram associadas teclas aceleradoras atravs do mtodo setAccelerator(), tendo que passar como parmetro um objeto do tipo KeyStroke, que identifica o caracter e a tecla de controle utilizados para fazer a combinao. Tendo definidos todos itens de menu, suas teclas de atalho e aceleradoras, estes foram adicionados ao menu menuArquivo, e este foi adiconado barra de menu BarraMenu. Percebe-se a existncia de linhas separatrias entre os itens, criadas pelo mtodo addSeparator(). Como os itens de menu respondem a eventos de ao, foi setado um ouvinte de eventos para cada um, a partir do addActionListener. Os mesmos passos foram seguidos para criar os menus menuEditar e menuAjuda. A criao do menuFormatar segue basicamente os mesmos passos, mas eles possuem, no lugar de itens de menu comuns, itens que abrem submenus, que contm outros itens especiais (caixas

60

de seleo e botes de rdio). Assim, no menu Formatar foram inseridos dois submenus: Cor e Fonte. Para a criao do menu Cor foi definido um objeto menuCor, do tipo JMenu, e foram adicionados seis itens de menu a partir do arranjo RBCores, do tipo JRadioButtonMenuItem. Por se tratar de botes de rdio, foi necessrio adicion-los tambm ao grupo grupoCores, do tipo ButtonGroup. Antes de adicionar o menuCor ao menuFormatar, foi setado o boto de rdio que inicia selecionado, pelo mtodo setSelected(). Para a criao do menu Fonte foi definido um objeto menuFonte, tambm do tipo JMenu, e foram adicionados: um grupo de botes de rdio, seguindo os mesmos passos j apresentados, uma linha separatria, e dois itens do tipo caixa de seleo, feitos a partir do arranjo CBNegritoItalico, do tipo JCheckBoxMenuItem. Ao final, o menuFonte foi adicionado ao menuFormatar, e esse, por sua vez, foi adicionado barra de menu. Da mesma forma que os itens de menu normais, tembm foi setado um ouvinte de eventos para cada um, a partir do addActionListener. Como j comentado, para o tratamento dos eventos, foi utilizada a interface ActionListener e implementado o mtodo actionPerformed() que, a partir do getActionCommand(), permite a comparao do que foi clicado com o texto do item de menu especfico. Como as opes Novo, Abrir e Salvar no possuem uma efetiva implementao, foi apresentada uma mensagem para cada uma delas. O item Sair encerra a aplicao. Os itens do menu Editar simplesmente executam os mtodos cut(), copy() e paste(), do objeto AreaTexto. O item Sobre tambm mostra apenas uma mensagem. Caso o item selecionado for algum dos constantes no menu Formatar, ento so utilizados mtodos como o setFont() e o setForeground(), para realizar as operaes desejadas, sendo confirmadas a partir do repaint().

3.10 Tratamento de Eventos Especiais


Alm dos eventos gerados por componentes de interface com o usurio, vistos at aqui, existem eventos especiais que podem ser ativados a qualquer hora, e no precisam estar associados a algum componente especfico. As prximas sees explicitam trs desses tipos de eventos: de foco, de janela, de mouse e de teclado. 3.10.1 Eventos de Foco Existem componentes que podem receber foco e outros no. Receber foco significa possuir prioridade sobre os outros componentes na digitao de teclas. Por exemplo, se um boto possuir o foco, no momento que for pressionada a barra de espaos, este ser o escolhido. Da mesma forma, se uma caixa de texto possuir o foco, quando forem digitados caracteres, nela que eles sero mostrados. Portanto, se o componente puder realizar algum tipo de ao advindo do pressionamento de teclas, ento, ele pode obter foco, caso contrrio, no. Logicamente, em um frame pode haver apenas um componente com foco, mas ele pode perder o foco se for pressionada a tecla Tab ou se um outro componente que pode receber foco for clicado com o mouse. Isso se existitem, no frame, outros componentes que podem receber foco. O componente que possui o foco mostra visualmente essa situao, como: um boto apresenta um retngulo pontilhado e uma caixa de texto apresenta o cursor piscando na rea destinada digitao. possvel mudar o foco via programao a qualquer momento, atravs do mtodo requestFocus(), mas s ir funcionar em resposta a um evento qualquer. 61

Como padro, os componentes do Swing so percorridos, pela tecla Tab, da esquerda para a direita e de cima para baixo, dentro do continer. Essa ordem conhecida como Ordem de tabulao, e o exemplo a seguir foi criado para realizar a verificao dessa ordem.
import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.border.*;

public class TesteDeFoco extends JFrame { private JTextField TextoUm; private JTextField TextoDois; private JTextField TextoTres; private JTextField TextoQuatro; private JButton BotaoUm; private JButton BotaoDois; private JButton BotaoTres; private JButton BotaoQuatro; public TesteDeFoco() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,170); setLocation(200,200); setTitle("Teste de Foco"); Container P = getContentPane(); P.setLayout(new GridLayout(2,1)); JPanel PainelFocoCima = new JPanel(); TextoUm = new JTextField("Texto Um",10); PainelFocoCima.add(TextoUm); TextoDois = new JTextField("Texto Dois",10); PainelFocoCima.add(TextoDois); BotaoUm = new JButton("Boto Um"); PainelFocoCima.add(BotaoUm); BotaoDois = new JButton("Boto Dois"); PainelFocoCima.add(BotaoDois); Border bordaPainelCima = BorderFactory.createEtchedBorder(); PainelFocoCima.setBorder(bordaPainelCima); P.add(PainelFocoCima); JPanel PainelFocoBaixo = new JPanel(); TextoTres = new JTextField("Texto Trs",10); PainelFocoBaixo.add(TextoTres); TextoQuatro = new JTextField("Texto Quatro",10); PainelFocoBaixo.add(TextoQuatro); BotaoTres = new JButton("Boto Trs"); PainelFocoBaixo.add(BotaoTres); BotaoQuatro = new JButton("Boto Quatro"); PainelFocoBaixo.add(BotaoQuatro); Border bordaPainelBaixo = BorderFactory.createEtchedBorder(); PainelFocoBaixo.setBorder(bordaPainelBaixo); P.add(PainelFocoBaixo); } public static void main(String[] args) {

62

JFrame fr = new TesteDeFoco(); fr.setVisible(true); } }

Figura 3.15. Sentido da Ordem de Tabulao

As legendas inseridas na figura 3.15 mostram o sentido natural seguido pelos componentes do Swing. Se existir um continer dentro de outro, no momento que entrar no continer interno, ir ser seguida a ordem padro at o seu ltimo componente, s ento voltar a percorrer os componentes do continer externo. possvel alterar essa ordem atravs do mtodo setNextFocusableComponent(). Por exemplo, para passar o foco do objeto TextoUm diretamente para o TextoTres, basta implementar o cdigo:
TextoUm.setNextFocusableComponent(TextoTres);

Nesse caso, aps o TextoUm viria o TextoTres, e depois retornaria o sentido normal, ou seja: TextoDois, BotaoUm, etc., a no ser que se altere novamente a ordem. Como visto anteriormente, o requestFocus() permite alterar o foco, mas apenas em resposta a algum evento. Isso bastante til se for necessrio testar o contedo de uma caixa de texto e, caso no esteja correto, emitir uma mensagem e no permitir a sada da caixa, como no exemplo a seguir.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class FocoAlterado extends JFrame implements FocusListener { private JTextField TextoUm; private JTextField TextoDois; public FocoAlterado() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,70); setLocation(200,200); setTitle("Alterando o Foco"); Container P = getContentPane(); JPanel PainelFoco = new JPanel(); TextoUm = new JTextField("Texto Um",10); PainelFoco.add(TextoUm);

63

TextoDois = new JTextField("Texto Dois",10); PainelFoco.add(TextoDois); P.add(PainelFoco); TextoUm.addFocusListener(this); } public void focusLost(FocusEvent evt) { Component origem = evt.getComponent(); if (origem == TextoUm && !evt.isTemporary()) if (TextoUm.getText().equals("")) { JOptionPane.showMessageDialog(this, "O valor deve ser digitado!", "Ateno", JOptionPane.ERROR_MESSAGE); TextoUm.requestFocus(); } } public void focusGained(FocusEvent evt) { } public static void main(String[] args) { JFrame fr = new FocoAlterado(); fr.setVisible(true); } }

Figura 3.16. Teste de entrada de dados em uma caixa de texto

A figura 3.16 mostra o que acontece se for feita a tentativa de sair da primeira caixa de texto sem digitar nada nela. Para que isso seja possvel, necessrio implementar os mtodos da interface FocusListener, focusLost() e focusGained(), que so invocados no momento que a origem do evento ganhar ou perder o foco. O parmetro FocusEvent uma classe que apresenta alguns mtodos importantes, como o getComponent(), que informa quem recebeu ou perdeu o foco e o isTemporary(), que informa se a mudana de foco foi permanente ou temporria, podendo ser, por exemplo, na ativao de uma outra janela e posterior retorno janela atual. No exemplo, para o objeto TextoUm, foi adicionado o ouvinte de eventos a partir do addFocusListener(). No mtodo focusLost() foi feito o teste se a origem do evento foi o TextoUm e se no foi uma perda de foco temporria. Caso seja verdadeiro e o contedo da caixa de texto esteja vazio, mostrada uma mensagem e devolvido o foco ao prprio TextoUm, no permitindo, dessa forma, sair da caixa de texto sem a digitao de algo. Como no foi realizada

64

nenhuma ao no ganho de foco, o mtodo focusGained() ficou vazio, lembrando a obrigatoriedade de se implementar todos os mtodos de uma interface. 3.10.2 Eventos de Janela Da mesma forma que os componentes, as janelas tambm possuem eventos possveis de acontecer. A classe JFrame o tipo de janela mais utilizado em Java, possuindo uma barra de ttulo e uma borda que se adaptam a plataforma onde o aplicativo est sendo executado. Isso significa que so incorporados recursos da GUI daquela plataforma especfica. Quando as janelas, incluindo o JFrame, gerarem algum evento, deve haver um ouvinte de eventos baseado na interface WindowListener para seu tratamento, e alguns mtodos podem ser implementados, como o caso do trecho de cdigo a seguir, que tem sido colocado nos exemplos vistos at aqui, com a funo de fechar o frame. O mtodo windowClosing() executado no momento que clicado no boto especfico para fechar a janela da plataforma corrente, sendo necessrio para isso encerrar a aplicao com o mtodo System.exit(0).
addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}});

Alm do mtodo windowClosing(), outros seis mtodos podem ser implementados. So eles:
windowActivated(): ocorre quando windowDeactivated():

a janela se torna ativa.

ocorre quando a janela se torna inativa, provavelmente na quando a janela aberta. o o

ativao de outra janela.


windowOpened(): ocorre

windowClosed(): ocorre quando a janela fechada. A diferena desse mtodo para windowClosing() que esse ltimo pode evitar que a janela seja fechada, enquanto windowClosed() executado aps o fechamento da janela. windowIconified(): ocorre quando windowDeiconified():

a janela minimizada.

ocorre quando a janela restaurada.

O exemplo a seguir mostra a primeira maneira de implementao de alguns mtodos da interface WindowListener.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EventosEmJanelas extends JFrame { public EventosEmJanelas() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { JOptionPane.showMessageDialog(null, "O frame ser fechado...");

65

System.exit(0); } public void windowOpened(WindowEvent e) { setTitle("Aberto"); } public void windowIconified(WindowEvent e) { setTitle("Minimizado"); } public void windowDeiconified(WindowEvent e) { setTitle("Restaurado"); } }); setSize(300,70); setLocation(200,200); } public static void main(String[] args) { JFrame fr = new EventosEmJanelas(); fr.setVisible(true); } }

Figura 3.17. Manipulao de eventos em janelas

Percebe-se que a estrutura adotada na maioria dos exemplos vistos at aqui foi seguida, acrescentando-se apenas os mtodos windowOpened(), na abertura do frame, windowIconified(), no ato de minimizar o frame, e windowDeiconified(), no ato de restaurar o frame. O resultado, apresentado na figura 3.17, mostra que foi feita uma alterao no ttulo do frame nesses mtodos. O mtodo windowClosing(), antes de finalizar a aplicao, mostra uma mensagem alertando o usurio que isso ir acontecer. Nota-se que os demais mtodos no foram implementados, pois nesse tipo de implementao no necessrio. A segunda maneira de realizar as mesmas tarefas mostrada no exemplo a seguir.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EventosEmJanelasSegundaForma extends JFrame implements WindowListener { public EventosEmJanelasSegundaForma()

66

{ addWindowListener(this); setSize(300,70); setLocation(200,200); } public void windowClosing(WindowEvent e) { JOptionPane.showMessageDialog(null, "O frame ser fechado..."); System.exit(0); } public void windowOpened(WindowEvent e) { setTitle("Aberto"); } public void windowIconified(WindowEvent e) { setTitle("Minimizado"); } public void windowDeiconified(WindowEvent e) { setTitle("Restaurado"); } public void windowClosed(WindowEvent e) { } public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e){ } public static void main(String[] args) { JFrame fr = new EventosEmJanelasSegundaForma(); fr.setVisible(true); } }

A execuo a mesma, mas a forma escolhida para a programao diferente. Observe que, em primeiro lugar, utilizou-se o implements WindowListener, e aps foi realizada a implementao dos mtodos, tornando-se obrigatria, dessa forma, que todos os mtodos estejam presentes, inclusive aqueles que no tem nenhum cdigo interno. 3.10.3 Eventos de Mouse Qualquer ao do mouse pode ser capturada como sendo um evento especfico, porm, na maioria das vezes, essas aes j so tratadas pelos componentes que esto sendo manipulados. Por exemplo, se for clicado em um boto, o mtodo a ser implementado o actionPerformed(), da interface ActionListener, no sendo necessrio tratar exclusivamente o clique do mouse. Porm, existem situaes que necessitam da implementao de linhas de cdigo que respondam a eventos de mouse, e quando isso acontece, os mtodos da interface MouseListener e MouseMotionListener devem ser implementados, tendo como parmetro um

67

objeto do tipo MouseEvent, que contm as informaes necessrias para o tratamento, como as coordenadas x e y de onde o evento ocorreu, por exemplo. A interface MouseListener possui cinco mtodos possveis de serem implementados. So eles:
mouseClicked(): ocorre quando h o pressionamento do mouse, com qualquer boto, e sua liberao sem o movimento do cursor. mousePressed(): ocorre

quando h o pressionamento de algum boto do mouse.

mouseReleased(): ocorre quando h a liberao de algum boto do mouse aps ter havido o pressionamento deste. mouseEntered(): ocorre quando o cursor do mouse entra na rea definida por um componente especfico.

ocorre quando o cursor do mouse sai da rea definida por um componente especfico.

mouseExited():

J a interface MouseMotionListener se preocupa mais com os eventos de movimento do mouse. Os dois mtodos exitentes so:
mouseMoved():

ocorre quando h o movimento do cursor do mouse em um componente

especfico.
mouseDragged(): ocorre quando h o pressionamento (mousePressed()) de um boto do mouse e posterior movimentao.

A fim de demonstrar o funcionamento do tratamento de eventos de mouse, o exemplo a seguir traz uma implementao para todos os mtodos de cada uma das duas interfaces.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EventosDeMouse extends JFrame implements MouseListener, MouseMotionListener { private JLabel Mensagem; private JButton BotaoOK; public EventosDeMouse() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); addMouseListener(this); addMouseMotionListener(this); setSize(400,100); setLocation(200,200); setTitle("Eventos de Mouse"); Container P = getContentPane(); P.setLayout(new BorderLayout()); JPanel PainelEMCentro = new JPanel();

68

BotaoOK = new JButton("OK"); PainelEMCentro.add(BotaoOK); P.add(PainelEMCentro,"Center"); JPanel PainelEMSul = new JPanel(); Mensagem = new JLabel(); PainelEMSul.add(Mensagem); P.add(PainelEMSul,"South"); BotaoOK.addMouseListener(this); } public void mouseClicked(MouseEvent e) { String botaoPressionado =e.getButton() == 1 ? "esquerdo" : (e.getButton() == 2 ? "do meio" : "direito"); Mensagem.setText("Boto " + botaoPressionado + " CLICADO nas cordenadas x = " + e.getX() + " y = " + e.getY()); } public void mousePressed(MouseEvent e) { String botaoPressionado =e.getButton() == 1 ? "esquerdo" : (e.getButton() == 2 ? "do meio" : "direito"); Mensagem.setText("Boto " + botaoPressionado + " PRESSIONADO nas cordenadas x = " + e.getX() + " y = " + e.getY()); } public void mouseReleased(MouseEvent e) { String botaoPressionado =e.getButton() == 1 ? "esquerdo" : (e.getButton() == 2 ? "do meio" : "direito"); Mensagem.setText("Boto " + botaoPressionado + " LIBERADO nas cordenadas x = " + e.getX() + " y = " + e.getY()); } public void mouseEntered(MouseEvent e) { Mensagem.setText("Mouse ENTROU no FRAME"); if (e.getSource() == BotaoOK) { Mensagem.setText("Mouse ENTROU no BOTO"); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } } public void mouseExited(MouseEvent e) { Mensagem.setText("Mouse SAIU do FRAME"); if (e.getSource() == BotaoOK) { Mensagem.setText("Mouse SAIU no BOTO"); setCursor(Cursor.getDefaultCursor()); } }

// mensagem no perceptvel

public void mouseMoved(MouseEvent e) { Mensagem.setText("Cursor MOVIDO para x = " + e.getX() +

69

" y = " + e.getY()); } public void mouseDragged(MouseEvent e) { Mensagem.setText("Cursor ARRASTADO para x = " + e.getX() + " y = " +e.getY()); } public static void main(String[] args) { JFrame fr = new EventosDeMouse(); fr.setVisible(true); } }

Figura 3.18. Manipulao de eventos de mouse

Apenas uma das mensagens, das vrias existentes, est sendo mostrada na figura 3.18. Antes de tudo, as duas interfaces esto sendo utilizadas, atravs do implements MouseListener, MouseMotionListener. Atravs do addMouseListener() e do addMouseMotionListener() foi setado o frame como sendo ouvinte de eventos dele mesmo. Para que o boto BotaoOK tambm pudesse responder aos eventos de clique, foi adicionado um ouvinte de eventos para ele. O resultado que, para cada um dos mtodos implementados, uma mensagem mostrada no label Mensagem, que fica no painel situado na parte sul do frame. Em algumas situaes, porm, algumas mensagens no podem ser vistas porque a mensagem de outro evento a sobrepe, como o caso de quando se entra no frame, onde a mensagem sobreposta por aquela emitida pelo mtodo mouseMoved(). Os mtodos mouseClicked(), mousePressed() e mouseReleased() simplesmente atualizam o label com: a mensagem de qual boto foi pressionado, informao adquirida pelo mtodo getButton(), que retorna um inteiro (1- boto esquerdo, 2- boto do meio e 3- boto direito); a ao realizada, se o boto foi clicado, pressionado ou liberado; e as coordenadas x e y, adquiridas pelos mtodos getX() e getY(). Como o boto tambm possui um ouvinte de eventos, a mensagem tambm atualizada quando o evento ocorre sobre ele. Percebe-se que as coordenadas x e y so especficas do boto. Nos mtodos mouseEntered() e mouseExited() h um tratamento especial para a ocorrncia do evento no boto. Quando o evento de entrada ou sada ocorre no frame, apenas uma mensagem adequada mostrada, porm, quando esse tipo de evento ocorre no boto, alm da mensagem, alterado o cursor para HAND_CURSOR na entrada e para o cursor padro na sada. Isso feito a partir do mtodo setCursor(), que tem como parmetro um objeto do tipo Cursor, onde, atravs do getPredefinedCursor(), possvel setar um dos cursores pr-definidos. Alguns desses tipos de cursor so mostrados na tabela 3.1.

70

DEFAULT_CURSOR HAND_CURSOR WAIT_CURSOR TEXT_CURSOR CROSSHAIR_CURSOR MOVE_CURSOR N_RESIZE_CURSOR SW_RESIZE_CURSOR SE_RESIZE_CURSOR E_RESIZE_CURSOR

(norte) ou S_RESIZE_CURSOR (sul) (sul- leste) ou NE_RESIZE_CURSOR (norte-leste) (sul-leste) ou NW_RESIZE_CURSOR (norte-leste) (leste) ou W_RESIZE_CURSOR (oeste)

Tabela 3.1. Exemplos de cursor existentes na plataforma Windows

Por fim, durante a movimentao sobre o frame, com ou sem o boto do mouse pressionado, uma mensagem mostrada, indicando o posicionamento. Os mtodos responsveis so o mouseMoved() e o mouseDragged(). Percebe-se que esse tipo de mensagem no aparece quando se passa em cima do boto. Isso ocorre porque no foi adicionado um ouvinte de eventos de movimento (addMouseMotionListener()) ao boto. 3.10.4 Eventos de Teclado Da mesma forma que o mouse, qualquer evento gerado pelo teclado pode ser tratado, mas isso s necessrio em situaes em que o evento ocorrido no esteja associado a um componente especfico. No mesmo exemplo utilizado para os eventos de mouse, um boto, para ser presssionado, pode ser clicado o mouse sobre ele, ou pode ser pressionada a barra de espaos quando o foco est sobre ele. Nesse caso, o evento a ser tratado no algum especfico de teclado, e sim o evento especfico para o boto. Nos casos especficos de tratamento de eventos de teclado, a interface utilizada a KeyListener, onde existem trs mtodos possveis de serem implementados, todos eles recebendo um objeto do tipo KeyEvent como parmetro. So eles:
keyPressed():

ocorre quando h o pressionamento de qualquer tecla. ocorre quando h a liberao de qualquer tecla, ocorrida aps o seu

keyReleased():

pressionamento. ocorre quando h o pressionamento de qualquer tecla que no seja uma tecla de ao, como o Home, End, Caps Lock, Shift, Alt, etc.
keyTyped():

O funcionamento dos eventos de teclado possveis demonstrado no exemplo a seguir, que simplesmente mostra a tecla, ou combinao de teclas que foi pressionada ou liberada. 71

import java.awt.*; import java.awt.event.*; import javax.swing.*; public class EventosDeTeclado extends JFrame implements KeyListener { private JLabel Mensagem; private int tecla = 0; private String teclaPressed = null; private char teclaTyped; private boolean entrouPressed; private boolean combinacao; public EventosDeTeclado() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); addKeyListener(this); setSize(250,100); setLocation(300,250); setTitle("Eventos de Teclado"); Container P = getContentPane(); Mensagem = new JLabel(); P.add(Mensagem); } public void keyPressed(KeyEvent e) { tecla = e.getKeyCode(); teclaPressed = e.getKeyText(tecla); entrouPressed = true; switch (tecla){ case KeyEvent.VK_SHIFT: teclaPressed = "Shift"; break; case KeyEvent.VK_CONTROL: teclaPressed = "Control"; break; case KeyEvent.VK_ALT: teclaPressed = "Alt"; break; case KeyEvent.VK_RIGHT: teclaPressed = "Direita"; break; case KeyEvent.VK_LEFT: teclaPressed = "Esquerda"; break; case KeyEvent.VK_UP: teclaPressed = "Cima"; break; case KeyEvent.VK_DOWN: teclaPressed = "Baixo"; break; } if (tecla == KeyEvent.VK_A && e.isShiftDown()) { combinacao = true; teclaPressed = "Shift + A"; } if (tecla == KeyEvent.VK_A && e.isControlDown()) { combinacao = true; teclaPressed = "Control + A"; } if (tecla == KeyEvent.VK_A && e.isAltDown()) { combinacao = true; teclaPressed = "Alt + A"; } Mensagem.setText("Tecla " + tecla + " - " + teclaPressed +" PRESSIONADA");

72

} public void keyReleased(KeyEvent e) { if (entrouPressed) { Mensagem.setText("Tecla " + tecla + " - " + teclaPressed + " LIBERADA"); combinacao = false; } else Mensagem.setText("Tecla " + teclaTyped + " LIBERADA"); } public void keyTyped(KeyEvent e) { if (!combinacao) { teclaTyped = e.getKeyChar(); entrouPressed = false; Mensagem.setText("Tecla " + teclaTyped + } } public static void main(String[] args) { JFrame fr = new EventosDeTeclado(); fr.setVisible(true); } }

" PRESSIONADA");

Figura 3.19. Manipulao de eventos de teclado

Um label Mensagem inserido no frame (figura 3.19) indica qual tecla ou combinao foi pressionada ou liberada. Para que isso seja possvel, necessrio implementar os trs mtodos da interface KeyListener. No exemplo, algumas variveis foram declaradas a fim de utilizar nos trs mtodos, j que, em algumas situaes, a mensagem de um sobreporia aquela emitida por outro mtodo. No keyPressed() a varivel tecla armazena o cdigo inteiro da tecla pressionada, a partir do getKeyCode(), e a varivel teclaPressed armazena a descrio da tecla pressionada, a partir do getKeyText(). No caso de se querer testar uma tecla especfica, necessrio testar o cdigo para ver se ele igual a alguma das constantes definidas na classe KeyEvent, sempre iniciadas por VK_. No exemplo, foi feito isso simplesmente para colocar uma descrio em portugus de algumas teclas na varivel teclaPressed. Aps, foi verificada a ocorrncia, e atualizada a varivel teclaPressed, das combinaes de teclas Shift+A, Control+A e Alt+A, atravs dos mtodos isShiftDown(), isControlDown() e isAltDown(), respectivamente. A varivel entrouPressed setada para true sempre que for executado o mtodo keyPressed() e a varivel combinacao setada para true sempre que forem

73

pressionadas as combinaes anteriormente citadas. Ao final, mostrado no label o cdigo e a descrio da tecla ou combinao pressionada. No mtodo keyTyped() a varivel teclaTyped obtm a tecla que foi pressionada, atravs do getKeyChar(), lembrando que apenas teclas que no so de ao ativam esse mtodo. A varivel entrouPressed setada para false para indicar a entrada no keyTyped(). Ao final, mostrada a tecla que foi pressionada. Tudo isso somente feito se no tiver sido pressionada uma combinao de teclas anteriormente, controlada pela varivel combinao. O mtodo keyReleased() executado aps o keyPressed() ou o keyTyped() tiver sido executado. Por isso a existncia da varivel entrouPressed, para dar mensagens diferentes na liberao das teclas. Adicionalmente, existe ainda o mtodo isActionKey(), que retorna true se a tecla pressionada for uma tecla de ao e false caso contrrio.

3.11 Aplicaes MDI, Menus Flutuantes e Barra de Ferramentas


Em Java, uma aplicao MDI (Mutilple Document Interface Interface de Mltiplos Documentos) caracterizada pela existncia de um frame principal, ou frame pai, que pode conter vrias outros frames internos, ou frames filhos. As operaes de manipulao do frame principal acarretam em efeitos nos frames internos. A ao de fechar, por exemplo, faz com que os frames internos que esto abertos tambm sejam finalizados. A rea de ao de um frame interno o prprio frame principal, no podendo ultrapassar os seus limites. Isso significa que, se um frame interno for maximizado, ele vai ocupar o espao delimitado pelo frame principal, esteja ele ocupando o espao que for da tela. Da mesma forma, ao minimizar um frame interno, este vai ficar localizado no rodap do frame principal. Para que se possa criar uma rea apta manipulao de frames internos, deve-se trabalhar com um objeto da classe JDesktopPane e inserir um objeto da classe JInternalFrame para cada frame interno que se deseja criar. A aplicao mostrada a seguir apresenta, alm do exemplo da aplicao MDI, a utilizao de uma barra de ferramentas e de menus flutuantes. Uma barra de ferramentas criada a partir da classe JToolBar, e nada mais do que um conjunto de botes que realizam aes, normalmente utilizada para criar acessos rpidos s principais tarefas da aplicao. Os menus flutuantes, criados a partir da classe JPopupMenu e comumente chamados de pop-up, so menus suspensos ativados normalmente pelo clique do boto direito do mouse, e podem aparecer em qualquer parte da rea que lhe foi destinada. Os itens de menu de um menu flutuante podem ter as mesmas caractersticas de um menu normal: ser apresentados na forma de caixa de seleo ou boto de rdio, com imagem associada, com teclas de atalho e teclas aceleradoras.
import import import import javax.swing.*; java.awt.event.*; java.awt.*; java.beans.*;

public class AplicacaoMDI extends JFrame implements ActionListener {

74

private private private private private private private

JDesktopPane DPane; JPopupMenu Menu; JButton abreFrameUm; JButton abreFrameDois; JButton sair; JInternalFrame IFrameUm; JInternalFrame IFrameDois;

public AplicacaoMDI() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(500,400); setLocation(100,50); setTitle("Aplicao MDI com Barra de Ferramentas e Menu Flutuante"); //criao do menu JMenuBar BarraMenu = new JMenuBar(); setJMenuBar(BarraMenu); JMenu menuArquivo = new JMenu("Arquivo"); menuArquivo.setMnemonic('A'); JMenuItem itemAbrirUm = new JMenuItem("Abrir Frame Interno Um...", new ImageIcon("EstrelaUm.gif")); itemAbrirUm.setMnemonic('U'); JMenuItem itemAbrirDois= new JMenuItem("Abrir Frame Interno Dois...", new ImageIcon("EstrelaDois.gif")); itemAbrirDois.setMnemonic('D'); JMenuItem itemSair= new JMenuItem("Sair", new ImageIcon("Sair.gif")); itemSair.setMnemonic('r'); itemSair.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK));; menuArquivo.add(itemAbrirUm); menuArquivo.add(itemAbrirDois); menuArquivo.addSeparator(); menuArquivo.add(itemSair); BarraMenu.add(menuArquivo); itemAbrirUm.addActionListener(this); itemAbrirDois.addActionListener(this); itemSair.addActionListener(this); //criao da barra de ferramentas JToolBar barra = new JToolBar(); abreFrameUm = new JButton(new ImageIcon("EstrelaUm.gif")); abreFrameUm.setToolTipText("Abre o Frame Interno Um"); abreFrameDois = new JButton(new ImageIcon("EstrelaDois.gif")); abreFrameDois.setToolTipText("Abre o Frame Interno Dois"); sair = new JButton(new ImageIcon("Sair.gif")); sair.setToolTipText("Encerra a aplicao"); barra.add(abreFrameUm); barra.add(abreFrameDois); barra.addSeparator(); barra.add(sair); abreFrameUm.addActionListener(this); abreFrameDois.addActionListener(this); sair.addActionListener(this); Container P = getContentPane(); P.setLayout(new BorderLayout()); P.add(barra,"North");

75

// criao da rea para insero de frames internos DPane = new JDesktopPane(); DPane.putClientProperty("JDesktopPane.dragMode", "outline"); P.add(DPane,"Center"); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); String item = evt.getActionCommand(); if (item == "Abrir Frame Interno Um..." || origem == abreFrameUm) { IFrameUm = new JInternalFrame("Frame Interno Um", true, true, true, true); IFrameUm.setSize(250,150); IFrameUm.setLocation(50,50); IFrameUm.setFrameIcon(new ImageIcon("EstrelaUm.gif")); IFrameUm.setVisible(true); JButton BotaoFechar = new JButton("Fechar"); BotaoFechar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { IFrameUm.setClosed(true); } catch (PropertyVetoException exc) { } } }); Menu = new JPopupMenu(); JMenuItem itemTitulo = new JMenuItem("Alterar Ttulo"); Menu.add(itemTitulo); itemTitulo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String retorno = JOptionPane.showInternalInputDialog(IFrameUm, "Digite novo ttulo", "Entrada", JOptionPane.QUESTION_MESSAGE); if (retorno != null) IFrameUm.setTitle(retorno); try { IFrameUm.setSelected(true); } catch (PropertyVetoException exc) { } } }); Menu.addSeparator(); JMenuItem itemFechar = new JMenuItem("Fechar"); Menu.add(itemFechar); itemFechar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { IFrameUm.setClosed(true); } catch (PropertyVetoException exc) { } } }); IFrameUm.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger())

76

Menu.show(e.getComponent(), e.getX(), e.getY()); } }); Container C = IFrameUm.getContentPane(); C.setLayout(new BorderLayout()); C.add(BotaoFechar,"South"); DPane.add(IFrameUm); try { IFrameUm.setSelected(true); } catch (PropertyVetoException exc) { } } else if (item == "Abrir Frame Interno Dois..." || origem == abreFrameDois) { IFrameDois = new JInternalFrame("Frame Interno Dois", false, true, false, false); IFrameDois.setSize(250,150); IFrameDois.setLocation(150,150); IFrameDois.setFrameIcon(new ImageIcon("EstrelaDois.gif")); IFrameDois.setVisible(true); JButton BotaoFechar = new JButton("Fechar"); BotaoFechar.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { IFrameDois.setClosed(true); } catch (PropertyVetoException exc) { } } }); Container C = IFrameDois.getContentPane(); C.setLayout(new BorderLayout()); C.add(BotaoFechar,"South"); DPane.add(IFrameDois); try { IFrameDois.setSelected(true); } catch (PropertyVetoException exc) { } } else if (item == "Sair" || origem == sair) System.exit(0); } public static void main(String args[]) { AplicacaoMDI fr = new AplicacaoMDI(); fr.setVisible(true); } }

77

Figura 3.20. Aplicao MDI Barra de Menu

A primeira parte do exemplo mostra a criao da barra de menu do frame principal, j adiantando que os frames internos tambm podem conter barras de menu individuais, o que no o caso do exemplo. A barra de menu BarraMenu, objeto da classe JMenuBar, definida como barra de menu do frame principal atravs do setJMenuBar(), e criado um nico menu nessa barra, o menuArquivo, onde so adicionados os itens de menu apresentados na figura 3.20. O processo de criao dos itens de menu segue o j visto em sees anteriores.

Figura 3.21. Aplicao MDI Barra de Ferramentas

Aps, a barra de ferramentas mostrada na figura 3.21 criada, e isso feito de maneira simples, a partir do objeto barra, da classe JToolBar. Ao criar esse objeto, todas as caractersticas referentes a uma barra de ferramentas so assimiladas, sendo necessrio apenas inserir botes com imagens atravs do mtodo add(). O tamanho de cada boto proporcional ao tamanho da imagem e cada um dos botes vai ter um comportamento normal, sendo necessrio adicionar um ouvinte de eventos (addActionListener()) a eles para virem a executar aes posteriormente. Na figura, tambm possvel verificar a existncia de uma dica de ferramenta, que aparece quando o cursor posicionado sobre um componente, para o boto sair, inserido em cada boto a partir do mtodo setToolTipText(). bom lembrar que qualquer componente que possui como superclasse a classe JComponent pode possuir uma dica de ferramenta. O separador existente entre os dois primeiros botes e o ltimo foi adicionado pelo mtodo addSeparator(). Ao final, o objeto barra includo na parte norte do frame.

78

Figura 3.22. Aplicao MDI Mobilidade da Barra de Ferramentas

Entre as caractersticas particulares de uma barra de ferramentas, uma que se destaca a que est sendo mostrada na figura 3.22, caracterizada pela sua mobilidade. A barra de ferramentas pode ser arrastada para qualquer uma das bordas do frame, ou ainda pode ser destacada do frame, sendo criado um frame especfico para ela. Nesse caso, se esse frame for fechado, a barra volta ao seu lugar de origem.

79

Figura 3.23. Aplicao MDI Frames Internos

Para que seja inserida a capacidade de receber frames internos, como mostra a figura 3.23, criando assim uma aplicao MDI, necessrio adicionar ao continer um objeto da classe JDesktopPane(). Foi isso que ocorreu na criao do objeto DPane, que, ao ser adicionado ao continer, tornou possvel a criao de frames internos. O mtodo putClientProperty() utilizado em seguida referente ao arrastar dos frames internos. Como padro, toda vez que se tentar movimentar um frame interno, este redesenhado a todo momento, enquanto estiver sendo arrastado. Isso pode causar desagrado a usurios que no tenham um bom equipamento, principalmente no que diz respeito ao vdeo, pois o desempenho pode no ser satisfatrio. Para evitar isso, o mtodo chamado faz com que, no ato de arrastar, apenas o contorno aparea e o frame s seja redesenhado na posio final desejada. O Windows, por exemplo, tem esse procedimento como padro no arrastar de janelas. No exemplo, os frames internos somente sero criados se um evento ocorrer, seja pela chamada do item de menu especfico, ou atravs da barra de ferramentas. Ento, no mtodo actionPerformed(), se for selecionado o item do menu Abrir Frame Interno Um..., ou se for clicado o primeiro boto da barra de ferramentas, ser mostrrado o primeiro frame interno. Para isso, foi criado um objeto IFrameUm a partir da classe JInternalFrame, passando cinco parmetros, seguindo a sintaxe:
JInternalFrame(String titulo, boolean redimensionar, boolean fechar, boolean maximizar, boolean minimizar)

80

Como todos os parmetro foram passados como true, o frame incorporou todas as funcionalidades permitidas a ele. Aps, como qualquer outro frame, ele foi configurado atravs de alguns mtodos:
setSize():

determina o tamanho do frame interno. determina a localizao do frame interno dentro do frame principal. um cone no frame interno.

setLocation():

setFrameIcon(): insere setVisible():

torna o frame interno visvel.

O boto BotaoFechar foi criado, j adicionando um ouvinte de eventos e implementando o cdigo para fechar o frame interno. O mtodo setClosed() responsvel por fechar o frame interno, mas necessrio tratar a exceo PropertyVetoException, do pacote java.beans, pois o frame pode ter problemas na ao de fechar, por algum motivo, e, nesse caso, se a exceo no for tratada, alm de no fechar, a aplicao seria abortada. O Java tem muito disso, quando a operao crtica e pode resultar na finalizao forada da aplicao, ele exige o tratamento da exceo. Se isso no for feito, no possvel executar o mtodo.

Figura 3.24. Aplicao MDI Menu Flutuante

Para esse frame interno, e apenas esse, foi criado um menu flutuante a partir do objeto Menu, da classe JPopupMenu (figura 3.24). Cada item de menu criado e adicionado ao menu flutuante da

81

mesma maneira que ocorre em um menu normal. No exemplo, no foi criado nenhum menu muito elaborado, tendo apenas dois itens: itemTitulo e itemFechar. O primeiro tem como ao a alterao do ttulo do frame pelo setTitle() a partir do retorno do que for digitado na caixa de dilogo de entrada interna showInternalInputDialog(). Normalmente, quando se utilizam frames internos, tambm so usadas caixas de dilogo internas. Elas so iguais s normais, mas, alm do nome, que recebe o termo Internal, permitem criar caixas de dilogo com as mesmas caractersticas dos frames internos, no sendo frames modais e possuem atuao dentro da rea definida pelo frame principal. No ato de fechar a caixa de dilogo, definindo o novo ttulo, o frameUm no volta a ficar selecionado. Para isso, foi utilizado o mtodo setSelected(), necessitando tambm do tratamento da exceo PropertyVetoException, pois pode ser que haja alguma rejeio nessa ao. O segundo item, o itemFechar, simplesmente executa o mtodo setClosed(), da mesma forma que foi feito no boto BotaoFechar. Com os itens criados, necessrio mostrar o menu de alguma forma e isso feito atravs do mtodo show(). A questo a ser resolvida : onde ele ir ser mostrado? Como a inteno fazer com que a rea de atuao desse menu flutuante seja somente o frame interno IFrameUm, nele que foi adicionado um ouvinte de eventos baseado na interface MouseListener e implementado o mtodo mouseReleased(). Isso porque o menu flutuante vai ser mostrado quando ocorrer uma ao do mouse. No cdigo da implementao, foi utilizado o mtodo isPopupTrigger() para verificar se o boto que foi clicado o correspondente ao boto padro para abrir menus flutuantes da plataforma atual, no caso do Windows, o boto direito. Os parmetros do mtodo show() envolvem o componente sobre o qual o menu flutuante ir aparecer e as coordenadas do clique do mouse, que onde o menu flutuante ir ser desenhado Por fim, criado um continer dentro do frame IFrameUm para receber o boto na parte inferior, o frame adicionado ao DPane, rea destinada a receber os frames internos e utilizado o setSelected() para selecionar o frame. Ainda no actionPerformed(), caso o item do menu selecionado for o Abrir Frame Interno Dois... ou se for clicado o segundo boto da barra de ferramentas, ser criado o segundo frame interno (objeto IFrameDois). Os procedimentos de criao e configurao so os mesmos, mas esse frame mais simples, possuindo o boto fechar e no possuindo o menu flutuante. Tambm foi setado para false as opes de redimensionar, minimizar e maximizar. Por fim, se o item do menu selecionado for o Sair ou se for clicado o terceiro boto da barra de ferramentas, a aplicao ser finalizada, no interessando se existem frames internos abertos ou no.

3.12 Aplicao com Vrios Frames


Existem situaes em que o estilo de aplicao MDI no aplicvel, e nem desejado. Nesses casos, as aplicaes devem trabalhar com um frame principal que abre outros frames normais, no internos, que possuem suas reas de atuao dentro da plataforma utilizada, e no no frame

82

principal, como acontece com os frames internos. O exemplo a seguir ilustra essa situao, com a criao de dois frames a partir de dois botes localizados no frame principal.
import javax.swing.*; import java.awt.event.*; import java.awt.*; public class VariosFrames extends JFrame implements ActionListener { private JButton abreFrameUm; private JButton abreFrameDois; private JFrame FrameDois; public VariosFrames() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(300,200); setLocation(150,150); setTitle("Criando Frames"); JPanel painelVF = new JPanel(); abreFrameUm = new JButton("Criar Frame Um"); abreFrameDois = new JButton("Criar Frame Dois"); painelVF.add(abreFrameUm); painelVF.add(abreFrameDois); abreFrameUm.addActionListener(this); abreFrameDois.addActionListener(this); Container P = getContentPane(); P.add(painelVF); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == abreFrameUm) { FrameUm frame = new FrameUm(); frame.show(); } if (origem == abreFrameDois) { FrameDois = new JFrame(); FrameDois.setTitle("Frame Dois"); FrameDois.setSize(200,100); FrameDois.setLocation(350,230); JPanel painelFDois = new JPanel(); painelFDois.setLayout(new BorderLayout()); JButton Fecha = new JButton("Fechar"); painelFDois.add(Fecha,"South"); Container P = FrameDois.getContentPane(); P.add(painelFDois); Fecha.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FrameDois.dispose(); } }); FrameDois.show();

83

} } public static void main(String args[]) { VariosFrames fr = new VariosFrames(); fr.setVisible(true); } } class FrameUm extends JFrame implements ActionListener { private JButton Fecha; public FrameUm() { setSize(200,100); setLocation(50,230); setTitle("Frame Um"); JPanel painelFUm = new JPanel(); painelFUm.setLayout(new BorderLayout()); Fecha = new JButton("Fechar"); painelFUm.add(Fecha,"South"); Fecha.addActionListener(this); Container P = getContentPane(); P.add(painelFUm); } public void actionPerformed(ActionEvent evt) { if (evt.getSource() == Fecha) { dispose(); } } }

Figura 3.25. Aplicao normal com criao de outros frames

Os dois frames criados tem o mesmo aspecto (figura 3.25), com posicionamento diferente, mas a criao de cada um diferente. Em primeiro lugar, no frame principal, foram inseridos dois botes no painel painelVF: abreFrameUm e abreFrameDois. O tratamento do evento de clicar do

84

primeiro boto simplesmente cria uma instncia da classe FrameUm, chamada frame, e mostra atravs do show(). A classe FrameUm um frame normal, que possui, em seu construtor, a definio do tamanho, localizao e ttulo, insero de um painel com um boto que, ao ser clicado, executa o mtodo dispose() para finalizar o frame.
FrameDois,

O segundo boto (abreFrameDois) tambm cria uma instncia de um frame, chamada mas faz isso internamente, sem criar uma classe a parte. Dependendo da complexidade do frame, isso pode ser um pouco complicado de se fazer, ou pelo menos, o cdigo fica um pouco mais confuso. Talvez seja uma melhor idia construir uma classe para cada frame a ser criado. Como as duas instncias de frame foram criadas dentro do frame principal, no momento que este for finalizado, automaticamente os outros frames tambm sero.

3.13 Tabelas
Existem aplicaes que necessitam apresentar dados na forma de tabelas, como o caso de aplicaes com banco de dados. Em Java, a classe JTable a responsvel pela tarefa de tratamento de dados em tabelas, permitindo a manipulao de linhas e colunas. As tabelas criadas a partir dessa classe so extremamente poderosas, possuindo muitos recursos para seu manuseio. Apesar da complexidade, relativamente fcil criar uma tabela funcional, com um comportamento pr-definido, como mostra o exemplo a seguir, que cria uma tabela simples.
import javax.swing.*; import java.awt.event.*; import java.awt.*; public class TabelaFormaUm extends JFrame implements ActionListener { private JButton BSair; public TabelaFormaUm() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(500,200); setLocation(100,50); setTitle("Tabela - Forma Um"); Container P = getContentPane(); P.setLayout(new BorderLayout()); // criao da tabela String[] colunas = new String []{"Referncia", "Descrio", "Estoque"}; Object[][] linhas = new Object [][] { {"01.015", "Televisor 15 polegadas", new Float(50)}, {"03.098", "Geladeira 300 litros", new Float(30)}, {"14.055", "Forno microondas", new Float(15)}, {"08.078", "DVD porttil", new Float(85)}, {"05.150", "Freezer vertical", new Float(25)}, {"10.004", "Aparelho de Som 300W", new Float(60)}}; JTable tabela = new JTable(linhas, colunas); JScrollPane rolagemTabela = new JScrollPane(tabela);

85

P.add(rolagemTabela,"Center"); // criao do painel de baixo JPanel pBaixo = new JPanel(); BSair = new JButton("Sair"); pBaixo.add(BSair); P.add(pBaixo,"South"); BSair.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == BSair) { System.exit(0); } } public static void main(String args[]) { TabelaFormaUm fr = new TabelaFormaUm(); fr.setVisible(true); } }

Figura 3.26. Uma tabela simples

A execuo do exemplo apresenta a tabela da figura 3.26. A criao dela foi baseada em um arranjo bidimensional, e no em um modelo de tabela, como o usual e mais indicado, visto no exemplo posterior. Os nomes das colunas foram definidos em um arranjo String chamado colunas. Os dados da tabela so armazenados em um arranjo bidimensional do tipo Object chamado linhas. O arranjo do tipo Object pelo fato de que possvel ter muitos tipos de objeto em uma coluna, como um JComboBox, por exemplo. Aps definir os arranjos, base da construo da tabela, esta criada com a passagem dos parmetros linhas e colunas, sendo depois inserida em um JScrollPane, para perimitir a existncia de barras de rolagem, e este, por fim, sendo inserido no continer. No painel de baixo inserido o boto BSair no painel pBaixo, que possui a tarefa de finalizar a aplicao.

86

Na execuo, algumas caractersticas so pr-definidas, como: cabealhos das colunas formatados automaticamente. largura das colunas distribudas igualmente. permisso para digitao dos dados, sendo que, se o valor no couber na clula, reticncias (...) so apresentadas, indicando essa situao. redimensionamento das colunas, bastando posicionar o cursor na linha separatria de duas colunas, no cabealho, e arrastar para o local desejado. seleo de linhas, permitindo a seleo de mltiplas linhas, com a tecla Shift, e de linhas intercaladas, com a tecla Ctrl. no caso de existncia de barras de rolagem, apenas os dados da tabela so movimentados, permanecendo o cabealho em seu lugar de origem. troca de colunas, onde uma coluna pode ser trocada com outra atravs do ato de arrastarsoltar, com o mouse posicionado no cabealho da coluna desejada.

3.13.1 Modelos de Tabela Apesar de fcil de ser criada, geralmente a maneira apresentada no primeiro exemplo no a mais indicada para criao de tabelas. Para que se possa ter maior controle sobre a tabela, necessrio criar um modelo de tabela, que se responsabilizar em manipular os dados. Tais modelos so implementados pela interface TableModel (AbstractTableModel e DefaultTableModel). O exemplo a seguir cria uma tabela com caractersticas particulares, baseado no DefaultTableModel.
import import import import javax.swing.*; javax.swing.table.*; java.awt.*; java.awt.event.*;

public class TabelaFormaDois extends JFrame implements ActionListener { private JButton btnExcluir; private JButton btnIncluir; private JButton btnMostrar; private JTextField texto; private JTable tabela; private int incCod = 0; public TabelaFormaDois() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Tabela - Forma Dois"); setSize(430,250); setLocation(100,50); Container P = getContentPane(); P.setLayout(new BorderLayout());

87

String[] tipos = {"Sim","No"}; JComboBox cbAtivo = new JComboBox(tipos); tabela = new JTable(); tabela.setModel(new DefaultTableModel( new Object [][] { }, new String [] { "ID", "Nome", "Sobrenome", "Limite", "Ativo" } )); tabela.getColumnModel().getColumn(0).setPreferredWidth(20); tabela.getColumnModel().getColumn(0).setResizable(false); tabela.getColumnModel().getColumn(1).setPreferredWidth(150); tabela.getColumnModel().getColumn(1).setResizable(true); tabela.getColumnModel().getColumn(2).setPreferredWidth(150); tabela.getColumnModel().getColumn(2).setResizable(true); tabela.getColumnModel().getColumn(3).setPreferredWidth(60); tabela.getColumnModel().getColumn(3).setResizable(true); tabela.getColumn(tabela.getColumnName(4)).setCellEditor (new DefaultCellEditor(cbAtivo)); tabela.getColumnModel().getColumn(4).setPreferredWidth(50); tabela.getColumnModel().getColumn(4).setResizable(true); tabela.getTableHeader().setReorderingAllowed(false); tabela.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); JScrollPane rolagemTabela = new JScrollPane(tabela); P.add(rolagemTabela,"Center"); // criao do Painel de baixo JPanel PTabSul = new JPanel(); btnIncluir = new JButton("Incluir"); PTabSul.add(btnIncluir); btnExcluir = new JButton("Excluir"); PTabSul.add(btnExcluir); btnMostrar = new JButton("Mostrar"); PTabSul.add(btnMostrar); texto = new JTextField("Nome Selecionado"); PTabSul.add(texto); P.add(PTabSul, "South"); btnExcluir.addActionListener(this); btnIncluir.addActionListener(this); btnMostrar.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == btnIncluir) { DefaultTableModel dtm = (DefaultTableModel)tabela.getModel(); dtm.addRow(new Object[]{ new Integer(++incCod), "Cliente " + incCod, "Endereo " + incCod, new Double(999.99), "Sim" }); } if (origem == btnExcluir) {

88

int linhas[] = tabela.getSelectedRows(); DefaultTableModel dtm = (DefaultTableModel)tabela.getModel(); for(int i = (linhas.length - 1); i >= 0; i--) dtm.removeRow(linhas[i]); } if (origem == btnMostrar) { if (tabela.getSelectedRow()>=0) texto.setText(tabela.getValueAt (tabela.getSelectedRow(),1).toString()); } } public static void main(String args[]) { TabelaFormaDois fr = new TabelaFormaDois(); fr.setVisible(true); } }

Figura 3.27. Uma tabela baseada no DefaultTableModel

A figura 3.26 apresenta o resultado da execuo aps clicar em alguns botes. A tabela foi criada normalmente, baseada no JTable. Aps isso, foi setado o modelo pelo mtodo setModel(), cujo parmetro a criao de um objeto DefaultTableModel, iniciando com um arranjo bidimensional vazio e um arranjo String com os nomes das colunas. Nenhum dado apresentado inicialmente porque isso uma tarefa do boto Incluir. Para cada coluna foi configurado o seu tamanho, a partir do mtodo setPreferredWidth() e se redimensinvel ou no, a partir do mtodo setResizable(). A coluna Ativo diferente das demais, pois apresenta um caixa de seleo. Para que isso seja possvel, foi definido um objeto cbAtivo, do tipo JComboBox, que, posteriormente, foi inserido na tabela a partir do mtodo setCellEditor(). de ser passveis de reorganizao a partir do mtodo setReorderingAllowed(), setado para false. O mtodo setAutoResizeMode() configura o modo de redimensionamento automtico das colunas da tabela, sendo que o AUTO_RESIZE_OFF desliga esse redimensionamento. Os outros modos existentes so: As colunas deixaram

89

AUTO_RESIZE_NEXT_COLUMN: redimensiona apenas a prxima coluna. AUTO_RESIZE_SUBSEQUENT_COLUMNS:

redimensiona todas as colunas subseqentes, sendo

o padro.
AUTO_RESIZE_LAST_COLUMN: redimensiona apenas a ltima coluna. AUTO_RESIZE_ALL_COLUMNS: redimensiona todas

as colunas da tabela.

Aps, a tabela inserida em um JScrollPane, para perimitir a existncia de barras de rolagem, e este, por fim, inserido no continer. O painel de baixo contm trs botes e uma caixa de texto. O primeiro boto, Incluir, ao ser clicado, utiliza o mtodo getModel() para criar o objeto dtm, do tipo DefaultTableModel. Tal objeto possui o mtodo addRow(), que usado para inserir uma linha na tabela, sempre com os mesmos campos, apenas mudando a numerao, controlada pela varivel inteira incCod. O segundo boto, Excluir, tambm cria um objeto dtm, alm de utilizar o getSelectedRows() para alimentar o arranjo int linhas com as linhas selecionadas. Um for percorrendo as linhas selecionadas foi feito para exclu-las a partir do mtodo removeRow(). Por fim, o terceiro boto, Mostrar, mostra na caixa de texto o contedo da clula 1 (Nome) da linha selecionada (getSelectedRow()). Isso capturado a partir do mtodo getValueAt(). 3.13.2 Modelo AbstractTableModel A classe DefaultTableModel uma classe com mtodos bsicos para trabalhar com os dados da JTable. Uma opo mais avanada criar uma classe prpria, estendendo a classe AbstractTableModel, que fornece diversos mtodos prontos, exceto:
public Object getValueAt(int row, int col):

retorna o objeto contido na clula

determinado por row e col.


public int getRowCount():

retorna o nmero de linhas da tabela. retorna o nmero de colunas da tabela.

public int getColumnCount():

A classe criada o prprio modelo da tabela e os mtodos apresentados devem ser implementados, obrigatoriamente. Muitos outros mtodos existem, e eles podem ser sobrepostos para realizar as aes desejadas para a tabela especfica. Por exemplo, o mtodo getColumnName() atribuir os nomes A, B, C, etc. aos nomes das colunas, a no ser que ele seja sobreposto para que atribua nomes significativos. Assim, necessrio sobrepor os mtodos existentes na classe AbstractTableModel da melhor forma possvel, para que atenda s necessidades do modelo especfico da tabela que ser implementada. Na verdade, uma vez tendo o modelo bem elaborado, possvel utiliza-lo na criao de vrias tabelas. O cdigo a seguir implementa vrias sobreposies de mtodos para exemplificar a criao de um modelo e de uma tabela baseada nesse modelo.
import javax.swing.*; import javax.swing.table.*;

90

import java.awt.*; import java.awt.event.*; import java.util.*; public class TabelaFormaTres extends JFrame implements ActionListener { private JButton btnExcluir; private JButton btnIncluir; private JButton btnMostrar; private JButton btnAlterar; private JButton btnMostrarClasse; private JTextField texto; private JTable tabela; private int incCod = 0; private ModeloTabela modelo; public TabelaFormaTres() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Tabela - Forma Trs"); setSize(600,250); setLocation(100,50); Container P = getContentPane(); P.setLayout(new BorderLayout()); // criao de um arranjo sem tamanho definido para insero // dinmica de objetos ArrayList dados = new ArrayList(); // criao de um arranjo para os ttulos no cabealho String[] colunas = new String[] { "ID", "Nome", "Sobrenome", "Limite", "Ativo" }; // criao de um arranjo para identificar se a clula editvel ou no boolean[] edicao = {false, true, true, false, true}; // Insero da primeira linha da tabela dados.add(new Object[]{ new Integer(++incCod), "Cliente " + incCod, "Endereo " + incCod, new Double(999.99), new Boolean(true) }); // criao da tabela baseada no modelo ModeloTabela modelo = new ModeloTabela(dados, colunas, edicao); tabela = new JTable(modelo); tabela.getColumnModel().getColumn(0).setPreferredWidth(50); tabela.getColumnModel().getColumn(0).setResizable(false); tabela.getColumnModel().getColumn(1).setPreferredWidth(200); tabela.getColumnModel().getColumn(1).setResizable(true); tabela.getColumnModel().getColumn(2).setPreferredWidth(200); tabela.getColumnModel().getColumn(2).setResizable(true); tabela.getColumnModel().getColumn(3).setPreferredWidth(80); tabela.getColumnModel().getColumn(3).setResizable(true); tabela.getColumnModel().getColumn(4).setPreferredWidth(55); tabela.getColumnModel().getColumn(4).setResizable(true); tabela.getTableHeader().setReorderingAllowed(false); tabela.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

91

JScrollPane rolagemTabela = new JScrollPane(tabela); P.add(rolagemTabela,"Center"); // criao do Painel de baixo JPanel PTabSul = new JPanel(); btnIncluir = new JButton("Incluir"); PTabSul.add(btnIncluir); btnExcluir = new JButton("Excluir"); PTabSul.add(btnExcluir); btnMostrar = new JButton("Mostrar"); PTabSul.add(btnMostrar); btnAlterar = new JButton("Alterar"); PTabSul.add(btnAlterar); btnMostrarClasse = new JButton("Classe"); PTabSul.add(btnMostrarClasse); texto = new JTextField(15); PTabSul.add(texto); P.add(PTabSul, "South"); btnExcluir.addActionListener(this); btnIncluir.addActionListener(this); btnMostrar.addActionListener(this); btnAlterar.addActionListener(this); btnMostrarClasse.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == btnIncluir) { modelo.addRow(new Object[]{ new Integer(++incCod), "Cliente " + incCod, "Endereo " + incCod, new Double(999.99), new Boolean(true) }); } if (origem == btnExcluir) { modelo.removeRow(tabela.getSelectedRow()); } if (origem == btnMostrar) { if (tabela.getSelectedRow()>=0) texto.setText(modelo.getValueAt(tabela.getSelectedRow(), tabela.getSelectedColumn()).toString()); } if (origem == btnAlterar) { if (tabela.getSelectedRow()>=0) modelo.setValueAt(texto.getText(),tabela.getSelectedRow(), tabela.getSelectedColumn()); } if (origem == btnMostrarClasse) { if (tabela.getSelectedRow()>=0) texto.setText(modelo.getColumnClass(

92

tabela.getSelectedColumn()).toString()); } } public static void main(String args[]) { TabelaFormaTres fr = new TabelaFormaTres(); fr.setVisible(true); } } class ModeloTabela extends AbstractTableModel { private ArrayList linhas = null; private String[] colunas = null; private boolean[] colEditavel; public ModeloTabela(ArrayList lin, String[] col, boolean[] editavel) { setLinhas(lin); setColunas(col); colEditavel = editavel; } public ArrayList getLinhas() { return linhas; } public void setLinhas(ArrayList dados) { linhas = dados; } public String[] getColunas() { return colunas; } public void setColunas(String[] nomes) { colunas = nomes; } public int getColumnCount() { return colunas.length; } public int getRowCount() { return linhas.size(); } public String getColumnName(int numCol) { return colunas[numCol];

93

} public boolean isCellEditable(int numCol) { return colEditavel[numCol]; } public Object getValueAt(int numLin, int numCol) { Object[] linha = (Object[])getLinhas().get(numLin); return linha[numCol]; } public void setValueAt(Object dado, int numLin, int numCol) { if (isCellEditable(numCol)) { Object[] linha = (Object[])getLinhas().get(numLin); linha[numCol] = dado; fireTableDataChanged(); } } public void addRow(Object[] dados) { getLinhas().add(dados); fireTableDataChanged(); } public void removeRow(int numLin) { getLinhas().remove(numLin); fireTableDataChanged(); } public Class getColumnClass(int numCol) { Object[] linha = (Object[])getLinhas().get(0); return linha[numCol].getClass(); } }

94

Figura 3.28. Uma tabela baseada no modelo criado a partir do AbstractTableModel

Antes de tudo, importante entender a classe ModeloTabela, que derivada de AbstractTableModel. O contedo das linhas armazenado em um objeto linhas, do tipo ArrayList. Um ArrayList permite armazenar qualquer tipo de objeto de uma forma dinmica, ou seja, no necessrio determinar o tamanho dele na sua declarao. Assim, ser possvel inserir ou excluir linhas a qualquer momento. Dois outros arranjos so criados: colunas, do tipo String, que armazena o nome das colunas, a ser mostrado no cabealho da tabela e; colEditavel, do tipo boolean, que armazena true ou false, conforme a coluna possa ser editvel ou no. Os primeiros quatro mtodos realizam o tratamento dos dados dos arranjos linhas e colunas. So eles:
public void setLinhas(ArrayList dados): public ArrayList getLinhas():

alimenta o arranjo das linhas

retorna o arranjo das linhas. arranjo das colunas.

public void setColunas(String[] nomes): alimenta o public String[] getColunas():

retorna o arranjo das colunas.

O contrutor da classe recebe trs parmetros: um ArrayList, para iniciar a tabela com as linhas desejadas; um arranjo String, que so os nomes das colunas, e; um arranjo boolean, com a indicao da possibilidade de edio de cada uma das colunas. No momento da instanciao em alguma aplicao, esses dados devem ser passados para que a tabela tenha uma situao inicial. Como explicado anteriormente, os nomes das colunas no seriam atribudos se no fosse sobreposto o mtodo getColumnName(), que retorna exatamente o contedo atribudo ao arranjo colunas. Alm disso, os dois mtodos obrigatrios getRowCount()e getColumnCount() so implementados, retornando o nmero de linhas e colunas do modelo. Os demais mtodos implementados so:

95

public boolean isCellEditable(int numCol):

retorna true se a coluna numCol for obrigatria.

editvel, e false, caso contrrio.


public Object getValueAt(int numLin, int numCol): Implementao Obtm o valor contido na clula de coordenadas numLin, numCol.

public void setValueAt(Object dado, int numLin, int numCol): define um novo valor para a clula de coordenadas numLin, numCol, se esta for editvel (testado a partir do mtodo isCellEditable()). Percebe-se que, aps inserido o objeto na clula, invocado o mtodo fireTableDataChanged(), que tem a funo de realizar a efetiva

alterao dos dados da tabela.


public void addRow(Object[] dados):

inclui uma linha na tabela a partir de um

arranjo de objetos.
public void removeRow(int numLin):

exclui a linha numLin da tabela. retorna a classe do objeto contido na

public Class getColumnClass(int numCol): coluna numCol.

A criao da tabela baseada nesse modelo, que resulta na aplicao mostrada na figura 3.28, feita na classe TabelaFormaTres. O ArrayList dados criado e adicionado a ele apenas uma nica linha, que um arranjo de vrios objetos de tipos diferentes. Alm de dados, o arranjo colunas criado e alimentado com os nomes das colunas da tabela; e o arranjo edicao criado com a indicao se cada coluna editvel ou no. Tais arranjos so passados como parmetro na criao do objeto da classe ModeloTabela, explicado anteriormente, chamado modelo, e este serve como parmetro na criao da JTable. Aps, como no exemplo anterior, so definidos os tamanhos de cada coluna (setPreferredWidth()), e se elas so redimensionveis ou no (setResizable()). Tambm igualmente ao exemplo anterior, as colunas deixam de ser reorganizveis, a partir do mtodo setReorderingAllowed(), setado para false, e configurado o modo de redimensionamento automtico das colunas da tabela, a partir do mtodo setAutoResizeMode(). Adicionalmente, o setSelectionMode() determina que s possvel selecionar uma linha por vez (SINGLE_SELECTION). Os outros dois valores possveis so: MULTIPLE_INTERVAL_SELECTION, que permite a seleo de uma ou mais linhas, de forma contgua ou no, e; SINGLE_INTERVAL_SELECTION, que permite a seleo de uma ou mais linhas, desde que seja de forma contgua. A tabela criada , ento, jogada em um JScrollPane e esse no continer. Aps, os botes Incluir, Excluir, Mostrar, Alterar e Classe so inseridos, alm do JTextField texto. As aes desses botes foram implementadas no ActionPerformed:
Incluir:

utiliza o mtodo addRow() do modelo para incluir uma nova linha no final da

tabela.

96

Excluir: utiliza o mtodo removeRow() do modelo para excluir a linha que est selecionada, capturada a partir do mtodo getSelectedRow().

mostra o contedo da clula no campo texto, caso haja uma linha selecionada. Isso feito pelo mtodo getValueAt(), passando como parmetro o nmero da linha (getSelectedRow()) e coluna (getSelectedColumn()) referente clula selecionada.
Alterar: Se houver linha selecionada, o contedo da clula selecionada alterado pelo valor contido no campo texto, a partir do mtodo setValueAt(). Classe: utiliza o mtodo getSelectedColumn() para capturar a classe da clula selecionada, mostrando no campo texto.

Mostrar:

3. Banco de Dados: Conectividade Utilizando JDBC


A pa
import import import import import import javax.swing.*; java.awt.*; java.awt.event.*; java.util.*; java.sql.*; javax.swing.border.*;

public class CriaTabelas extends JFrame implements ActionListener { private JButton btnExcluir; private JButton btnIncluir; private JButton btnLimpar; private JButton btnConectar; private JButton btnDesconectar; private JButton btnCriar; private JTextField nomeCampo; private JTextField tipoCampo; private JTextField fonteDados; private JTextField usuario; private JPasswordField senha; private JTextField nomeTabela; private JList lista; private Vector campos; private JLabel lblCon; private Connection con; private String chavePrimaria; public CriaTabelas() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Wizard para criao de tabelas de BD"); setSize(500,320); setLocation(100,100); Container P = getContentPane(); P.setLayout(new BorderLayout()); campos = new Vector();

97

// criao do primeiro painel JPanel PNorte = new JPanel(); PNorte.setLayout(new BorderLayout()); JPanel PNorteNorte = new JPanel(); PNorteNorte.add(new JLabel("Fonte de Dados")); fonteDados = new JTextField(13); PNorteNorte.add(fonteDados); PNorteNorte.add(new JLabel("Usurio")); usuario = new JTextField(7); PNorteNorte.add(usuario); PNorteNorte.add(new JLabel("Senha")); senha = new JPasswordField(5); PNorteNorte.add(senha); PNorte.add(PNorteNorte,"North"); JPanel PNorteCentro = new JPanel(); btnConectar = new JButton("Conectar Banco"); btnConectar.addActionListener(this); PNorteCentro.add(btnConectar); lblCon = new JLabel("No Conectado"); PNorteCentro.add(lblCon); btnDesconectar = new JButton("Desconectar Banco"); btnDesconectar.addActionListener(this); PNorteCentro.add(btnDesconectar); PNorte.add(PNorteCentro,"Center"); P.add(PNorte, "North"); // criao do segundo painel JPanel PCentro = new JPanel(); PCentro.add(new JLabel("Nome da Tabela")); nomeTabela = new JTextField(10); PCentro.add(nomeTabela); lista = new JList(); lista.setVisibleRowCount(8); lista.setFixedCellWidth(200); lista.setFixedCellHeight(15); lista.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); PCentro.add(new JScrollPane(lista)); btnCriar = new JButton("Criar Tabela"); btnCriar.addActionListener(this); PCentro.add(btnCriar); btnLimpar = new JButton("Limpar lista"); btnLimpar.addActionListener(this); PCentro.add(btnLimpar); Border borda = BorderFactory.createEtchedBorder(); PCentro.setBorder(borda); P.add(PCentro, "Center"); // criao do terceiro painel JPanel PSul = new JPanel(); PSul.add(new JLabel("Nome")); nomeCampo = new JTextField(10); PSul.add(nomeCampo); PSul.add(new JLabel("Tipo")); tipoCampo = new JTextField(10); PSul.add(tipoCampo); btnIncluir = new JButton("Incluir"); PSul.add(btnIncluir); btnExcluir = new JButton("Excluir"); PSul.add(btnExcluir);

98

P.add(PSul, "South"); btnExcluir.addActionListener(this); btnIncluir.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == btnConectar) { String sFonte = "jdbc:odbc:" + fonteDados.getText().trim(); String sUsuario = usuario.getText().trim(); String sSenha = senha.getText().trim(); try { System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver"); con = DriverManager.getConnection(sFonte, sUsuario, sSenha); JOptionPane.showMessageDialog(this, "Banco conectado com sucesso!", "Mensagem", JOptionPane.WARNING_MESSAGE); lblCon.setText("Conectado"); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); }catch (Exception e) { // demais excees e.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } if (origem == btnDesconectar) { try { con.close(); lblCon.setText("Desconectado"); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel desconectar o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } if (origem == btnIncluir) { String item = nomeCampo.getText() + " " + tipoCampo.getText(); if (campos.isEmpty()) { JOptionPane.showMessageDialog(this, "O primeiro campo ser a chave primria da tabela",

99

"Mensagem", JOptionPane.WARNING_MESSAGE); chavePrimaria = nomeCampo.getText(); } campos.addElement(item); lista.setListData(campos); } if (origem == btnExcluir) { if (lista.getSelectedIndex()>= 0) { campos.removeElementAt(lista.getSelectedIndex()); lista.setListData(campos); } } if (origem == btnLimpar) { campos.removeAllElements(); lista.setListData(campos); } if (origem == btnCriar) { String itens = campos.toString(); itens = itens.substring(1,itens.length()-1); String sentencaSQL = "CREATE TABLE " + nomeTabela.getText().trim() + " (" + itens + ", PRIMARY KEY (" + chavePrimaria + "))" ; try{ Statement st = con.createStatement(); st.executeUpdate(sentencaSQL); JOptionPane.showMessageDialog(this, "Tabela criada com sucesso!", "Mensagem", JOptionPane.WARNING_MESSAGE); }catch (SQLException eSQL) { eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel criar a tabela!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } } public static void main(String args[]) { CriaTabelas fr = new CriaTabelas(); fr.setVisible(true); } }

100

A
import import import import import import javax.swing.*; java.awt.*; java.awt.event.*; java.sql.*; java.util.*; javax.swing.table.*;

public class Consulta extends JFrame implements ActionListener { private JButton btnSair; private JButton btnPesqNome; private JButton btnPesqCod; private JTextField nome; private JTextField codigo; private Connection con; private ModeloTabelaBD modelo; private JTable tabela; private Statement sentenca; private ResultSet registros; public Consulta() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Consulta a Banco de Dados"); setSize(500,320); setLocation(100,100); Container P = getContentPane(); P.setLayout(new BorderLayout()); // conecta o banco con = conectaBanco("jdbc:odbc:ODBCBancoExemplo", null, null); // criao do primeiro painel JPanel PNorte = new JPanel();

101

PNorte.setLayout(new BorderLayout()); JPanel PNorteNorte = new JPanel(); PNorteNorte.add(new JLabel("Digite nome")); nome = new JTextField(13); PNorteNorte.add(nome); btnPesqNome = new JButton("Pesquisar por nome"); PNorteNorte.add(btnPesqNome); btnPesqNome.addActionListener(this); PNorte.add(PNorteNorte,"North"); JPanel PNorteCentro = new JPanel(); PNorteCentro.add(new JLabel("Digite cdigo")); codigo = new JTextField(7); PNorteCentro.add(codigo); btnPesqCod = new JButton("Pesquisar por cdigo"); PNorteCentro.add(btnPesqCod); PNorte.add(PNorteCentro,"Center"); btnPesqCod.addActionListener(this); P.add(PNorte, "North"); // criao da tabela // criao de um array para insero dinmica de objetos ArrayList dados = new ArrayList(); // criao de um array para os ttulos no cabealho String[] colunas = new String[] { "Cdigo", "Nome", "Endereo"}; // criao de um array para identificar se a clula editvel ou no boolean[] edicao = {false, false, false}; // seleciona todos os registros da tabela Clientes e joga no ArrayList try { String sentencaSQL = "SELECT * FROM Clientes ORDER BY Codigo"; sentenca = con.createStatement(); registros = sentenca.executeQuery(sentencaSQL); boolean proximoRegistro = registros.next(); if (!proximoRegistro) { JOptionPane.showMessageDialog(this, "Nenhum registro foi encontrado!", "Mensagem", JOptionPane.WARNING_MESSAGE); } else do { dados.add(new Object[]{ new Integer(Integer.parseInt(registros.getString("Codigo"))), registros.getString("Nome"), registros.getString("Endereco") }); } while (registros.next()); sentenca.close(); }catch (SQLException eSQL) { eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel carregar os dados!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } // criao da tabela baseada no modelo ModeloTabelaBD modelo = new ModeloTabelaBD(dados, colunas, edicao); tabela = new JTable(modelo); tabela.getColumnModel().getColumn(0).setPreferredWidth(50);

102

tabela.getColumnModel().getColumn(0).setResizable(false); tabela.getColumnModel().getColumn(1).setPreferredWidth(200); tabela.getColumnModel().getColumn(1).setResizable(true); tabela.getColumnModel().getColumn(2).setPreferredWidth(240); tabela.getColumnModel().getColumn(2).setResizable(true); tabela.getTableHeader().setReorderingAllowed(false); tabela.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane rolagemTabela = new JScrollPane(tabela); P.add(rolagemTabela, "Center"); // criao do terceiro painel JPanel PSul = new JPanel(); btnSair = new JButton("Sair"); PSul.add(btnSair); P.add(PSul, "South"); btnSair.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == btnPesqNome) { Selecao("SELECT * FROM Clientes WHERE NOME LIKE '%" + nome.getText() + "%' ORDER BY NOME"); } if (origem == btnPesqCod) { Selecao("SELECT * FROM Clientes WHERE CODIGO = " + codigo.getText() + " ORDER BY CODIGO"); } if (origem == btnSair) { try { con.close(); System.exit(0); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel desconectar o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } } public void Selecao(String sentencaSQL) { // apaga todas as linhas da tabela for (int i= modelo.getRowCount()-1; i >= 0; i--) modelo.removeRow(i); try { sentenca = con.createStatement(); registros = sentenca.executeQuery(sentencaSQL); boolean proximoRegistro = registros.next(); if (!proximoRegistro)

103

{ JOptionPane.showMessageDialog(this, "Nenhum registro foi encontrado!", "Mensagem", JOptionPane.WARNING_MESSAGE); } else do { modelo.addRow(new Object[]{ new Integer(Integer.parseInt(registros.getString("Codigo"))), registros.getString("Nome"), registros.getString("Endereco") }); } while (registros.next()); sentenca.close(); }catch (SQLException eSQL) { eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel carregar os dados!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } public Connection conectaBanco(String sFonte,String sUsuario,String sSenha) { Connection conexao = null; try { System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver"); conexao = DriverManager.getConnection(sFonte, sUsuario, sSenha); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); }catch (Exception e) { // demais excees e.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } return conexao; } public static void main(String args[]) { Consulta fr = new Consulta(); fr.setVisible(true); } } class ModeloTabelaBD extends AbstractTableModel { private ArrayList linhas = null;

104

private String[] colunas = null; private boolean[] colEditavel; public ModeloTabelaBD(ArrayList lin, String[] col, boolean[] editavel) { setLinhas(lin); setColunas(col); colEditavel = editavel; } public ArrayList getLinhas() { return linhas; } public void setLinhas(ArrayList dados) { linhas = dados; } public String[] getColunas() { return colunas; } public void setColunas(String[] nomes) { colunas = nomes; } public int getColumnCount() { return colunas.length; } public int getRowCount() { return linhas.size(); } public String getColumnName(int numCol) { return colunas[numCol]; } public boolean isCellEditable(int numCol) { return colEditavel[numCol]; } public Object getValueAt(int numLin, int numCol) { Object[] linha = (Object[])getLinhas().get(numLin); return linha[numCol]; } public void setValueAt(Object dado, int numLin, int numCol)

105

{ if (isCellEditable(numCol)) { Object[] linha = (Object[])getLinhas().get(numLin); linha[numCol] = dado; fireTableDataChanged(); } } public void addRow(Object[] dados) { getLinhas().add(dados); fireTableDataChanged(); } public void removeRow(int numLin) { getLinhas().remove(numLin); fireTableDataChanged(); } public Class getColumnClass(int numCol) { Object[] linha = (Object[])getLinhas().get(0); return linha[numCol].getClass(); } }

D
import javax.swing.*; import java.awt.*;

106

import import import import

java.awt.event.*; java.sql.*; java.util.*; javax.swing.table.*;

public class Cadastro extends JFrame implements ActionListener { private JButton btnSair; private JButton btnIncluir; private JButton btnAlterar; private JButton btnExcluir; private JButton btnPesqNome; private JTextField nome; private Connection con; private ModeloTabelaBD modelo; private JTable tabela; private Statement sentenca; private ResultSet registros; public Cadastro() { addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e){System.exit(0);}}); setTitle("Consulta a Banco de Dados"); setSize(500,320); setLocation(100,100); Container P = getContentPane(); P.setLayout(new BorderLayout()); // conecta o banco con = conectaBanco("jdbc:odbc:ODBCBancoExemplo", null, null); // criao do primeiro painel JPanel PNorte = new JPanel(); PNorte.setLayout(new FlowLayout()); PNorte.add(new JLabel("Digite nome")); nome = new JTextField(13); PNorte.add(nome); btnPesqNome = new JButton("Pesquisar"); PNorte.add(btnPesqNome); btnPesqNome.addActionListener(this); P.add(PNorte, "North"); // criao da tabela // criao de um array para insero dinmica de objetos ArrayList dados = new ArrayList(); // criao de um array para os ttulos no cabealho String[] colunas = new String[] { "Cdigo", "Nome", "Endereo"}; // criao de um array para identificar se a clula editvel ou no boolean[] edicao = {false, false, false}; // criao da tabela baseada no modelo ModeloTabelaBD modelo = new ModeloTabelaBD(dados, colunas, edicao); tabela = new JTable(modelo); tabela.getColumnModel().getColumn(0).setPreferredWidth(50); tabela.getColumnModel().getColumn(0).setResizable(false); tabela.getColumnModel().getColumn(1).setPreferredWidth(200); tabela.getColumnModel().getColumn(1).setResizable(true); tabela.getColumnModel().getColumn(2).setPreferredWidth(240); tabela.getColumnModel().getColumn(2).setResizable(true); tabela.getTableHeader().setReorderingAllowed(false);

107

tabela.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane rolagemTabela = new JScrollPane(tabela); P.add(rolagemTabela, "Center"); // criao do terceiro painel JPanel PSul = new JPanel(); btnIncluir = new JButton("Incluir"); btnAlterar = new JButton("Alterar"); btnExcluir = new JButton("Excluir"); btnSair = new JButton("Sair"); PSul.add(btnIncluir); PSul.add(btnAlterar); PSul.add(btnExcluir); PSul.add(btnSair); P.add(PSul, "South"); btnIncluir.addActionListener(this); btnAlterar.addActionListener(this); btnExcluir.addActionListener(this); btnSair.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object origem = evt.getSource(); if (origem == btnPesqNome) { Selecao("SELECT * FROM Clientes WHERE NOME LIKE '%" + nome.getText() + "%' ORDER BY NOME"); } if (origem == btnIncluir) { FrameCadastro frame = new FrameCadastro(con, null, null, null, 'I'); frame.show(); } if (origem == btnAlterar) { if (tabela.getSelectedRow()>=0) { FrameCadastro frame = new FrameCadastro(con, modelo.getValueAt(tabela.getSelectedRow(),0).toString(), modelo.getValueAt(tabela.getSelectedRow(),1).toString(), modelo.getValueAt(tabela.getSelectedRow(),2).toString(), 'A'); frame.show(); } else JOptionPane.showMessageDialog(this, "No existe registro selecionado!\n", "Mensagem", JOptionPane.WARNING_MESSAGE); } if (origem == btnExcluir) { try { if (JOptionPane.showConfirmDialog(null,"Confirma Excluso?", "Confirmao", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == 0) { sentenca = con.createStatement();

108

String sentencaSQL ="DELETE FROM Clientes WHERE Codigo= " + modelo.getValueAt(tabela.getSelectedRow(),0).toString(); sentenca.executeUpdate(sentencaSQL); sentenca.close(); Selecao("SELECT * FROM Clientes WHERE NOME LIKE '%" + nome.getText() + "%' ORDER BY NOME"); } }catch (SQLException eSQL) { eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel realizar a operao!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } if (origem == btnSair) { try { con.close(); System.exit(0); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel desconectar o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } } public void Selecao(String sentencaSQL) { // apaga todas as linhas da tabela for (int i= modelo.getRowCount()-1; i >= 0; i--) modelo.removeRow(i); try { sentenca = con.createStatement(); registros = sentenca.executeQuery(sentencaSQL); boolean proximoRegistro = registros.next(); if (!proximoRegistro) { JOptionPane.showMessageDialog(this, "Nenhum registro foi encontrado!", "Mensagem", JOptionPane.WARNING_MESSAGE); } else do { modelo.addRow(new Object[]{ new Integer(Integer.parseInt(registros.getString("Codigo"))), registros.getString("Nome"), registros.getString("Endereco") }); } while (registros.next()); sentenca.close(); }catch (SQLException eSQL) { eSQL.printStackTrace();

109

JOptionPane.showMessageDialog(this, "No foi possvel carregar os dados!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } public Connection conectaBanco(String sFonte,String sUsuario,String sSenha) { Connection conexao = null; try { System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver"); conexao = DriverManager.getConnection(sFonte, sUsuario, sSenha); }catch (SQLException eSQL) { // excees de SQL eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); }catch (Exception e) { // demais excees e.printStackTrace(); JOptionPane.showMessageDialog(this, "Falha na conexo com o banco!\n" + "Mensagem: " + e.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } return conexao; } public static void main(String args[]) { Cadastro fr = new Cadastro(); fr.setVisible(true); } } class FrameCadastro extends JFrame implements ActionListener { private JButton OK; private JButton Cancelar; private JTextField txtCodigo; private JTextField txtNome; private JTextField txtEndereco; private Connection conexao; private char TipoOperacao; public FrameCadastro(Connection con, String Cod, String Nome, String Endereco, char Tipo) { conexao = con; TipoOperacao = Tipo; setSize(250,140); setLocation(220,190); Container P = getContentPane(); JPanel painelFC = new JPanel();

110

painelFC.setLayout(new FlowLayout()); painelFC.add(new JLabel("Cdigo")); txtCodigo = new JTextField(15); txtCodigo.setText(Cod); if (Tipo == 'A') { txtCodigo.setEditable(false); setTitle("Alterao"); } else setTitle("Incluso"); painelFC.add(txtCodigo); painelFC.add(new JLabel("Nome")); txtNome = new JTextField(15); txtNome.setText(Nome); painelFC.add(txtNome); painelFC.add(new JLabel("Endereo")); txtEndereco = new JTextField(15); txtEndereco.setText(Endereco); painelFC.add(txtEndereco); OK = new JButton("OK"); Cancelar = new JButton("Cancelar"); painelFC.add(OK); painelFC.add(Cancelar); OK.addActionListener(this); Cancelar.addActionListener(this); P.add(painelFC,"Center"); } public void actionPerformed(ActionEvent evt) { if (evt.getSource() == OK) { if (txtCodigo.getText().trim().equals("") || txtNome.getText().trim().equals("")) { JOptionPane.showMessageDialog(this, "Campos Cdigo e Nome devem ser preenchidos!\n", "Erro", JOptionPane.ERROR_MESSAGE); } else { try { Statement sentenca = conexao.createStatement(); String sentencaSQL = null; if (TipoOperacao == 'I') sentencaSQL = "INSERT INTO Clientes (" + "Codigo, Nome, Endereco) "+ "VALUES ("+ Integer.parseInt(txtCodigo.getText())+", '"+ txtNome.getText() + "', '" + txtEndereco.getText()+"')"; else sentencaSQL = "UPDATE Clientes SET Nome = '" + txtNome.getText() + "', Endereco = '" + txtEndereco.getText()+"' WHERE Codigo = " + Integer.parseInt(txtCodigo.getText());

111

sentenca.executeUpdate(sentencaSQL); sentenca.close(); dispose(); }catch (SQLException eSQL) { eSQL.printStackTrace(); JOptionPane.showMessageDialog(this, "No foi possvel realizar a operao!\n" + "Mensagem: " + eSQL.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); } } } if (evt.getSource() == Cancelar) { dispose(); } } }

D D d

3. AWT Avanado
Imagens e desenhos mais complexos no podem ser feitos a partir da classe Graphics. necessrio utilizar pacotes existentes na API Java 2D, que permite produzir desenhos de mais alta qualidade.

112

3.14 Java 2D
O Java 2D apresenta pacotes de classes com mtodos para desenhos grficos com um nvel maior de complexidade. Alguns desses pacotes: java.awt.image, java.awt.geom, java.awt.print, java.awt.Graphics2D. Com o Java 2D possvel produzir uma variedade maior de figuras geomtricas, com padres diferentes de preenchimento, alm de ter controle sobre os desenhos criados, podendo move-los, gira-los ou alonga-los.

3.15 Imagens
A classe Image a responsvel pelo carregamento de imagens armazenadas em disco. Novam d

113

Bibliografia
Cesta, Andr Augusto. Tutorial: A Linguagem de Programao JAVA. Instituto de Computao. UNICAMP, 1996. Disponvel em http://www.dcc.unicamp.br Davis, Stephen R. Aprenda Java agora. 2.ed. Rio de Janeiro : Campus, 1997. 401p. Deitel, Harvey M. Java : como programar. 3.ed. Porto Alegre : Bookman, 2001. 1201p. Flanagan, David. Java : o guia essencial. Rio de Janeiro : Campus, 2000. 718 p. Lemay, Laura; Cadenhead, Rogers. Aprenda em 21 dias Java 2. Rio de Janeiro : Campus, 1999. 661p. Schtzer, Waldeck; Massago, Sadao. Programao Java. Departamento de Matemtica Universidade Federal de So Carlos UFSCar. 1999. Disponvel em: http://www2.dm.ufscar.br/~waldeck/curso/java/

Sites de Interesse
www.java.sun.com - Site ofical do Java. www.javafree.com.br - Comunidade de desenvolvedores Java. www.portaljava.com.br - Comunidade de desenvolvedores Java.

114

Você também pode gostar