• Nenhum resultado encontrado

1. Programação Visual Básica - Java Programação GUI Basico

N/A
N/A
Protected

Academic year: 2018

Share "1. Programação Visual Básica - Java Programação GUI Basico"

Copied!
114
0
0

Texto

(1)

Programação JAVA

1. Programação Visual Básica

A Interface Gráfica com o Usuário, também conhecido como GUI -

Graphical User Interface

,

em Java, é feita através de bibliotecas de classes, sendo que a primeira a surgir foi a AWT

(

Abstract Window Toolki

t). A AWT surgiu já na versão 1.0, mas se tornou confiável a partir da

versão 1.1. A maneira como as classes dessa biblioteca trabalham garante a criação dos

elementos da interface de usuário seguindo o comportamento destinado às ferramentas GUI

nativas de cada plataforma (Windows, Mac, Solaris, ...).

Alguns exemplos destes elementos são: botões, listas, menus, componentes de textos, containers

(janelas e barras de menus), caixas de diálogo para abrir ou salvar arquivos, além de elementos

para manipulação de imagens, fontes e cores.

A portabilidade de plataforma funcionava bem em aplicações simples, mas aplicações que

envolviam elementos mais complexos, como menus e barras de rolagem, por exemplo,

apresentavam diferenças de comportamento conforme a plataforma. O que aconteceu foi que as

aplicações visuais feitas em Java não se pareciam, e nem tinham as mesmas funcionalidades, com

as aplicações convencionais de cada plataforma.

A partir da versão 2 do Java, a JFC (Java Foundation Classes) apresentou novos recursos para a

construção da GUI das aplicações, o que melhorou muito os problemas de portabilidade. São

eles:

Java 2D: novas funções para desenhos e gráficos.

Drag & Drop: clicar, arrastar, copiar e colar.

Swing: biblioteca de classes extensão da AWT, onde são apresentados novos

componentes de interface e o que é conhecido por

look and feel

, que é uma adaptação

perfeita da GUI ao sistema operacional específico de desenvolvimento.

É bom salientar que o Swing não substitui o AWT, mas é o kit de ferramentas GUI mais utilizado

para desenvolvimento de aplicações visuais. O AWT continua existindo, mantendo a mesma

arquitetura criada para o Java versão 1.1.

O Swing possui muito mais recursos, além de garantir maior portabilidade e, em boa parte dos

casos, é mais fácil de usar. Isso não significa que ou se utiliza AWT ou se utiliza Swing,

normalmente o que acontece é que elementos das duas bibliotecas são utilizados conjuntamente

nas aplicações.

(2)

como Delphi e VisualBasic, que são voltadas exclusivamente para esse fim. Boa parte da

elaboração da interface da aplicação tem que ser feita manualmente, o que exige bastante

trabalho.

1.1 Frames

Na AWT, a janela de mais alto nível de uma aplicação (não está contida dentro de nenhuma

outra) é denominada

Frame. No Swing, existe uma versão chamada JFrame, que é

derivada/estendida da classe Frame, possuindo alguns poucos métodos adicionais relacionados à

manipulação da disposição visual dos frames .Todos os outros métodos são derivados da classe

Frame. Um frame pode conter diversos outros componentes da GUI.

Para se definir um frame básico baseado em AWT, deve-se:

Importar o pacote java.awt.*.

Estender a classe Frame.

Ter um método main() para criar o objeto a partir do operador new.

Torná-lo visível.

Assim, o código 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 visível, é possível utilizar fr.show(); no lugar de fr.setVisible(true);.

Percebe-se que não é possível fechá-lo utilizando o botão fechar. Por enquanto, ela deve ser

encerrada forçando a finalização do processo (ex.: finalizar tarefa no Windows, ou terminar

processo na ferramenta específica de desenvolvimento).

Figura 1.1. Frame FrameUm

O frame criado não possui tamanho definido, nem título ou posicionamento. Para personalizar o

frame é necessário inserir um método construtor com as instruções necessárias. Exemplo:

import java.awt.*;

public class FrameDois extends Frame {

public

FrameDois() //construtor {

setTitle("Frame Dois"); // título do Frame

(3)

setLocation(200, 100); // x: 200 pixels y: 100 pixels }

public static void main (String[] args) {

FrameDois fr = new FrameDois(); fr.setVisible(true);

} }

A figura 1.2 mostra o resultado da execução, um frame com largura 300 x 200 pixels

(setSize()), com o título “Frame Dois” (setTitle()), que não permite redimensionamento

(setResizable()).

Figura 1.2. Frame FrameDois

Além 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 resolução atual da tela. No

exemplo, o frame fica posicionado em 200 pixels para x e 100 pixels para y.

(0 ,0) x

y

(x, y)

Figura 1.3. Sistema de coordenadas do Java

Conforme já mencionado, o frame ainda não pode ser fechado. Para que isso aconteça é

necessário ter uma maneira de se ter a notificação de quando ele é fechado. A partir da

manipulação desse evento, mostrado no exemplo a seguir, é possível fechar o frame. É necessário

importar o pacote java.awt.event.*

para manipular eventos do AWT. O modelo de eventos e

os demais eventos de janela serão vistos em seções posteriores.

(4)

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 Três"); // título do Frame

setSize(300, 200); // largura: 300 pixels altura: 200 pixels setResizable(false); // não 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 relação ao posicionamento, dependendo da resolução da tela onde o frame será aberto,

pode se ter situações bem desagradáveis, como, por exemplo, o frame ser aberto e ficar com parte

fora da tela. É necessário então posicionar o frame em coordenadas que independam da resolução

utilizada. O exemplo a seguir abrirá um frame com a metade do tamanho da tela, posicionado no

centro, respeitando a resolução.

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);

} }

(5)

método

getImage(), para carregar a imagem (extensão .gif) e jogar em um objeto da classe Image, para depois setar o ícone através do setIconImage().

O mesmo exemplo pode ser feito baseado na biblioteca Swing, classe JFrame, mudando apenas a

derivação e importando o pacote javax.swing.*, assim:

import java.awt.*;

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

public class FrameQuatro extends JFrame {

... }

Os exemplos apresentados nas próximas seções criarão frames baseado na classe JFrame.

1.2 Mostrando Textos e Linhas no Frame

Para que seja possível mostrar textos em um frame é necessário criar um objeto baseado na classe

Graphics, que será responsável pelo gerenciamento da área gráfica a ser desenhada, controlando

cores, tipos de fontes, etc. A classe Component possui um método paint() que aceita um objeto

Graphics como parâmetro. Esse método, na classe de origem, não faz nada, por isso ele deve ser

sobrescrito com a chamada de métodos que realizam operações de escrita, pintura, desenho, etc.

Para efetuar a sobreposição do método paint() deve-se ter o cabeçalho:

public void paint(Graphics g)

A partir disso, métodos 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);

(6)

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 método drawString(String s, int x, int y) realiza a mostragem de um texto em uma

posição definida por x e y. O método 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 método setColor() seleciona a cor que é utilizada para todas as operações de desenho dentro

do contexto gráfico ou componente. Um parâmetro Color define a cor a ser usada, sendo que as

treze cores padrão, apresentadas na tabela 1.1, estão definidas na classe java.awt.Color.

black (preto) magenta (magenta)

blue (azulo) orange (laranja)

cyan (ciano) pink (rosa)

darkGray (cinza-escuro) red (vermelho)

gray (cinza) white (branco)

(7)

lightGray (cinza-claro)

Tabela 1.1. Cores definidas em java.awt.Color

Além das cores pré-definidas, pode-se criar novas cores baseadas no conteúdo RGB

(red-vermelho, green-verde, blue-azul), expressos por inteiros de 0 a 255. O exemplo a seguir

apresenta a criação 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); }

}

(8)

O método drawRect(int x, int y, int width, int height) desenha um retângulo com a

cor definida em

setColor(), iniciando nas coordenadas x,y, tendo uma largura width e uma

altura height. O método fillRect(int x, int y, int width, int height) faz a mesma

coisa, mas preenche o retângulo.

1.4 Fontes

O método responsável 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 específico; o estilo

pode ser: PLAIN – regular, BOLD – negrito e ITALIC – itálico, sendo possível 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 itálico tamanho 16", 20, 50); g.setFont(new Font("Monospaced", Font.BOLD + Font.ITALIC, 14));

g.drawString("Fonte Monospaced negrito e itálico tamanho 14", 20, 80); g.setFont(f);

g.drawString("Novamente Fonte SansSerif itálico tamanho 16", 20, 110); }

public static void main (String[] args) {

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

}

(9)

Figura 1.6. Frame Fontes

Em termos de portabilidade, deve-se tomar cuidado quanto a fontes que não existem em alguns

sistemas operacionais. O ideal é trabalhar com fontes comuns em sistemas operacionais

diferentes. O modelo do AWT define cinco fontes disponíveis em qualquer sistema operacional.

São elas: Serif, Monospaced, SansSerif, Dialog e DialogInput.

1.5 Outras Formas Geométricas

Além das formas já apresentadas, existem várias outras possíveis, a maioria com a opção de

preenchimento ou não, a partir da precedência 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 Geométricas"); }

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);

(10)

}

public static void main (String[] args) {

FormasGeometricas fr = new FormasGeometricas(); fr.setVisible(true);

} }

Figura 1.7. Frame Fontes

Várias formas geométricas foram desenhadas no frame. Funcionamento de cada método:

drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight): Desenha um retângulo 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, int arcWidth, int arcHeight): Idem a drawRoundRect, mas preenche o retângulo.

draw3DRect(int x, int y, int width, int height, boolean raised): Desenha

um retângulo 3D, iniciando nas coordenadas x,y, tendo uma largura width e uma altura

height, e um valor lógico para indicar a aparência do 3D.

fill3DRect(int x, int y, int width, int height, boolean raised): Idem a draw3DRect, mas preenche o retângulo.

drawOval(int x, int y, int width, int height): Desenha uma forma oval,

baseado nas coordenadas do retângulo 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 retângulo 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.

(11)

drawPolygon(int[] xPoints, int[] yPoints, int nPoints): Desenha um

polígono, baseado nas coordenadas dos arranjos x,y.

fillPolygon(int[] xPoints, int[] yPoints, int nPoints):

Idem

a

drawPolygon, mas preenche o arco.

1.6 Imagens

A classe

Image é a responsável pelo carregamento de imagens armazenadas em disco.

Novamente, é necessário utilizar um objeto do tipo Toolkit para obter uma imagem, através do

método 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);

(12)

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, através do método copyArea(int x, int y, int width, int height, int dx, int dy), que copia o

conteúdo da área que começar nas coordenadas x,y com largura width e altura height, em um

local a uma distância

dx,dy. Para realizar essa tarefa, foi necessário descobrir o tamanho da

imagem, através getWidth()

e do getHeight().

1.7 Contêiners

Contêiners servem de repositório de outros componentes, como botões, por exemplo. Alguns

exemplos de contêiners: JFrame, JPanel e JApplet. Um JFrame é uma janela de mais alto nível;

um JPanel é um contêiner usado para agrupar componentes, normalmente dentro de um JFrame;

um JApplet permite a execução em navegadores da Web. Pode-se desenhar algo diretamente no

frame ou definir um contêiner, como um painel, por exemplo, e desenhar nele. Não é considerada

uma boa prática de programação desenhar diretamente no frame, pois ele foi projetado para ser

contêiner de componentes específicos, como barras de menu, por exemplo. Os painéis devem ser

utilizados para agrupar outros componentes. Exemplo de adição 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() {

(13)

{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. Contêiner 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 método

paintComponent(), que está definido na classe JComponent, e recebe um parâmetro do tipo Graphics. Tal método é chamado automaticamente

toda vez que a janela é redesenhada, como na criação e no redimensionamento. Se, por algum

motivo, se desejar redesenhar o conteúdo no painel, o método a ser chamado é o repaint(), que

se encarrega de executar novamente o

paintComponent(). O super.paintComponent(g) faz

com que o método da superclasse seja executado também. Isso normalmente é feito em

sobreposições de métodos, quando se deseja criar algo a mais que o método definido na

superclasse. A criação de uma classe derivada de JFrame é feita a seguir, e um objeto Container

é criado para depois adicionar (add) o painel. O método

getContentPane() retorna a área de

conteúdo 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 contêiners, sendo que cada contêiner possui um gerenciador padrão, mas pode ser

alterado através da chamada ao método

setLayout() do contêiner específico. Por exemplo, o

gerenciador padrão do JPanel é o FlowLayout, que coloca os componentes em um tamanho

pré-definido da esquerda para a direita e de cima para baixo no contêiner. Outros gerenciadores de

layout existentes: GridLayout, BorderLayout, BoxLayout e GridBagLayout.

1.8.1

Gerenciador FlowLayout

Para que seja possível verificar a diferença entre alguns deles, exemplos são demonstrados nas

próximas seções, começando exatamente pelo gerenciador FlowLayout, padrão do JPanel. Nos

exemplos, são definidos objetos botão a partir da classe JButton.

(14)

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("Três")); 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 padrão do JPanel, não seria necessário setar o layout

através do setLayout(new FlowLayout());. O alinhamento dos componentes fica centralizado

e, caso algum compontnte não caiba em uma linha, é jogado para a linha seguinte, como mostra a

figura 1.10. É possível alterar o alinhamento, passando-o como parâmetro na determinação do

layout (LEFT, RIGHT ou CENTER), assim:

setLayout(new FlowLayout(FlowLayout.RIGHT));

(15)

O

GridLayout é um gerenciador que organiza os componentes em linhas e colunas espaçadas

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("Três")); 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

(16)

setLayout(). Os componentes são adicionados a partir da posição na parte superior esquerda da

grade, seguindo para a direita até preencher a linha e passar para baixo.

Também é possível espaçar os componentes horizontal e verticalmente. Nesse caso, na definição

do layout, deve-se passar esses valores também. O layout abaixo, por exemplo, define 5 pixels de

espaçameno horizontal e 8 pixels de espaçamento 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("Três"),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);

(17)

Figura 1.12. Gerenciador de Layout GridLayout

Na figura 1.12 se observa o resultado da aplicação, com um botão em cada localização geográfica

dentro do painel. O BorderLayout é o gerenciador padrão para os contêiners JWindow e JFrame.

Não é necessário ter todas as localizações preenchidas. Se alguma das localizações (norte, sul,

leste ou oeste) não for ocupada, as demais ocupam o lugar da(s) omitida(s). Porém, se a

localização central não for ocupada, ela ficará vazia.

Na definição do layout é possível determinar o espaçamento horizontal e vertical entre as

localizações. O layout abaixo, por exemplo, define 5 pixels de espaçameno horizontal e 8 pixels

de espaçamento vertical:

setLayout(new BorderLayout(5,8));

1.8.4

Gerenciador BoxLayout

Os gerenciadores de layout foram criados ainda na versão 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

invés de utilizar o

BoxLayout diretamente, pode-se usar um outro contêiner 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("Três"));

add(Box.createHorizontalStrut(30)); add(new JButton("Quatro"));

add(Box.createHorizontalGlue()); add(new JButton("Cinco"));

add(Box.createHorizontalGlue()); }

}

(18)

{

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 botões não ficaram distanciados uniformemente. Isso porque

dois métodos foram utilizados: o

createHorizontalGlue(), que determina um espaçamento

variável, conforme o tamanho da janela e o

createHorizontalStrut(), que determina um

espaçamento fixo, determinado pelo seu parâmetro.

1.8.5

Gerenciador GridBagLayout

O gerenciador GridBagLayout é bastante flexível, permitindo posicionamento dos componentes

em relação aos outros. Assim, é possível criar praticamente qualquer tipo de layout. Por ser mais

flexível, é também mais difícil de ser utilizado. O construtor não possui argumentos e a aparência

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

Descrição

int gridx, gridy

Utilizado para controlar o posicionamento dos componentes

na grade do layout.

int weightx, weighty

Utilizado para especificar um percentual de aumento do local

destinado aos componentes, que irão aumentar também se

estiverem expandidos.

int fill

Utilizado para expandir o componente a fim de preencher o

espaço reservado a ele.

(19)

componente irá se espalhar.

int anchor

Utilizado para controlar a posição do componente, caso ele

não esteja espalhado.

int ipadx, ipady

Utilizado para controlar o aumento do tamanho mínimo dos

componente.

Insets insets

Utilizado para controlar o afastamento entre componentes.

Tabela 1.1. Campos da classe GridBagConstraints

A utilização desses campos são demonstradas através de exemplos. O primeiro deles mostra um

GridBagLayout com cinco botões inseridos em posições 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("Três"), 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) {

(20)

} }

Figura 1.13. Gerenciador de Layout GridBagLayout com cinco botões

O resultado, mostrado na figura 1.13, apresenta cinco botões inseridos em coordenadas que

indicam a presença de três linhas por três colunas (0, 1 e 2). O tamanho da grade é definido por

essas coordenadas, sendo possível, por isso, ter quantas colunas e linhas se desejar. O método

addGridBag() criado serve para auxiliar na definição dos valores que os campos de controle do GridBagConstraints irão assumir.

Para que os botões preencham toda a área do painel é necessário definir, no construtor, a restrição

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("Três"), 1, 1); addGridBag(new JButton("Quatro"), 2, 1); addGridBag(new JButton("Cinco"), 1, 2); }

Figura 1.14. Gerenciador de Layout GridBagLayout ocupando todo espaço disponível

O resultado é o preenchimento de todo painel, como mostra a figura 1.14. O fill ainda pode ser

definido como:

HORIZONTAL, preenchendo o espaço horizontal disponível; VERTICAL,

preenchendo o espaço vertical disponível e;

NONE, não preenchendo o espaço disponível. Os

campos weigthx e weigthy devem receber um valor diferente de zero, pois o preenchimento não

ocorre se esse valor for igual a zero, que é o valor default.

(21)

número de linhas) e largura (em número de colunas) através 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("Três"), 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 botão Um ocupou três colunas e uma

linha, enquanto o botão Quatro ocupou duas linhas e uma coluna. No momento que o número de

colunas/linhas é definido, todos os componentes utilizarão esse tamanho de espaço daí pra diante,

a não ser que este seja redefinido.

É possível também definir o tamanho dos componentes através do peso atribuído 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("Três"), 2, 0); restricoes.weightx = 4.0;

(22)

Figura 1.16. Gerenciador de Layout GridBagLayout com determinação de pesos

Para que o exemplo fique igual ao apresentado na figura 1.16, é necessário mudar o setSize()

do frame para (400,60). Os botões ficam dispostos em uma única linha, com tamanhos

diferentes, determinados pela atribuição de seus respectivos pesos, sabendo-se que o valor

específico do peso não é o que importa, e sim as proporções relativas entre os botões 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. Além disso, é possível fixar uma posição

do componente, dentro do espaço reservado a ele, desde que ele não esteja espalhado em mais

que uma coluna e/ou linha. Isso é feito através 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("Três"), 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

(23)

concedida. O valor padrão é CENTER, e os outros valores possíveis são: NORTH, NORTHEAST, EAST,

SOUTHEAST, SOUTH, SOUTHWEST, WEST, e NORTHWEST.

Através do campo insets é possível indicar as distâncias entre os componentes do layout. Uma

classe

Insets possui valores para as quatro direções: cima, baixo, direita e esquerda, dando

muita flexibilidade ao layout. O valor padrão é (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("Três"), 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 espaço adicional de três pixels para cada

uma das direções: cima, baixo, direita e esquerda.

1.8.6

Layouts Compostos

Normalmente, ao querer criar um determinado layout, a utillização de um gerenciador apenas não

é suficiente. É necessário, então, 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);

} }

(24)

public PainelTipoFlow() {

setLayout(new FlowLayout()); add(new JButton("Um")); add(new JButton("Dois")); add(new JButton("Três")); 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 localização sul do

painel com layout

BorderLayout. Isso é uma prática bastante comum para se alcançar layouts

com disposição de componentes que satisfaçam aos objetivos da aplicação. A localização do

centro ficou vazia porque isso é uma característica do

BorderLayout: não expandir as outras

localizações se a do centro estiver vazia.

2. Interface Gráfica com o Usuário e a Manipulação de Eventos

(25)

seções descrevem o modelo de manipulação de eventos AWT a partir de alguns elementos GUI

simples.

2.1

O Modelo de Manipulação de Eventos AWT

É muito comum encontrar, em linguagens de programação visuais, o tratamento dos eventos que

são gerados por seus componentes visuais. Com Java não é diferente, tanto na biblioteca AWT,

quanto na biblioteca Swing, existem classes para manipulação de eventos. A maneira como essa

manipulação acontece não é tão simples como nas linguagens Delphi e Visual Basic, exigindo

que haja a designação 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. É necessário lembrar que as

interfaces possuem métodos

abstract para serem redefinidos pelas classes que as

implementarem. Além disso, “todos” os métodos

abstract devem ser redefinidos. O registro

desses ouvintes é feito em objetos conhecidos como

origem do evento

, como um botão, por

exemplo. A origem envia objetos eventos para o(s) ouvinte(s) na ocorrência de um evento, e

esse(s) usa(m) essa informação para determinar o que será feito em reação ao evento.

Um exemplo de registro de um objeto ouvinte painel em um objeto de origem botão:

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 método actionPerformed(), que recebe um objeto ActionEvent como parâmetro. Assim:

public class MeuPainel extends Jpanel implements ActionListener {

...

public void actionPerformed(ActionEvent evt) {

//código para a reação ao evento }

}

2.2

Eventos em Botões

O exemplo a seguir apresenta um painel com três botões, sendo que o próprio painel é definido

como ouvinte para monitorar os eventos que podem acontecer nos botões.

import java.awt.*;

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

class PainelEventosBotao extends JPanel implements ActionListener {

(26)

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 Botões"); Container P = getContentPane(); P.add(new PainelEventosBotao()); }

public static void main(String[] args) {

JFrame fr = new TesteEventosBotao(); fr.setVisible(true);

(27)

Figura 2.1. Eventos em objetos JButton

Na criação do painel, três botões foram adicionados a ele. Logo após, foi determinado que o

próprio painel (this) seria o ouvinte das ações dos três botões. O método actionPerformed() é

o único método da interface ActionListener, por isso apenas ele deve ser implementado. Esse

método recebe como parâmetro um objeto do tipo ActionEvent, que fornece informações sobre

o evento ocorrido, sendo o local para implementar as ações a serem realizadas. A classe

TesteEventosBotao adiciona o painel com os botões.

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 próprio painel e, quando for dado um

Enter em qualquer uma das caixas, o conteúdo 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,"Código = "+ 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() {

(28)

{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 código e logo a seguir for pressionada

a tecla Enter. Novamente, o método 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 método

showMessageDialog(), pertencente à

classe JOptionPane.

2.4

Utilizando Eventos para Alterar o Aspecto Visual da Aplicação

O Look and Feel é a aparência que sua aplicação irá tomar, definindo a forma como seus

componentes serão mostrados na tela. Ao utilizar componentes da biblioteca Swing, o aspecto

visual é determinado pelo estilo Metal, mas existem outros, e a alteração é feita através do

método

UIManager.setLookAndFeel(), passando como parâmetro 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 após, é necessário chamar o método

SwingUtilities.updateComponentTreeUI

para

atualizar todo o conjunto de componentes.

import java.awt.*;

(29)

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 {

(30)

{

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 execução após selecionar cada um dos aspectos visuais. É

importante salientar que o aspecto Windows só funciona no próprio Windows, pois a Sun não

disponibiliza esse aspecto para outras plataformas. Alguns Look And Feel’s podem gerar uma

exceção, por não existirem ou não serem suportados em determinadas plataformas, como o que

ocorreu como aspecto Mac. É importante salientar também que, a depender do layout utilizado

em uma determinada aplicação, podem ocorrer problemas de aparência, por que tamanhos de

botões, caixas de texto e outros componentes variam de plataforma para plataforma, e podem

fazer com que a aparência de uma aplicação 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 métodos que devem ser sobrepostos, os parâmetros e os objetos origens

dos eventos.

Interface

Métodos

Parâmetros

Origens

ActionListener actionPerformed ActionEvent getActionCommand getModifiers

Button List MenuItem TextField AdjustmentListener AdjustementValueChanged AdjustmentEvent

(31)

getAdjustmentType getValue

ItemListener ItemStateChanged ItemEvent getItem getItemSelectable getStateChange Checkbox CheckboxMenuItem Choice List

TextListener TextValueChanged TextEvent TextComponent ComponentListenter componentMoved componentHidden componentResized componentShown ComponentEvent getComponent Component ContainerListener componentAdded componentRemoved ComponentEvent getChild getContainer Container FocusListener focusGained

focusLost FocusEvent isTemporary Component KeyListener keyPressed keyReleased keyTyped KeyEvent getKeyChar getKeyCode getKeyModifiersText getKeyText isActionKey Component MouseListener mousePressed mouseReleased mouseEntered mouseExited mouseClicked MouseEvent getClickCount getX getY getPoint translatePoint isPopupTrigger Component MouseMotionListener mouseDragged

mouseMoved MouseEvent Component

WindowListener windowClosing windowOpened windowIconified windowDeiconified windowClosed windowActivated windowDeactivated WindowEvent getWindow 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 são: java.awt.event e javax.swing.event.

3. Utilizando a Biblioteca Swing para a Interface com o Usuário

(32)

As próximas seções se destinam a apresentação dos principais componentes do Swing, além dos

botões e caixas de texto, que foram vistos no capítulo anterior.

3.1 Labels e Botões – Classes JLabel e JButton

Os labels e botões são componentes muito utilizados e de fácil manipulação. Como já visto, para

tratar eventos em botões é necessário implementar o método

actionPerformed() da interface ActionListenter. O exemplo a seguir mostra as principais ações que podem ser realizadas em

labels, acionadas a partir do clique de botões.

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 botão um"); LabelDois = new JLabel("Label para o botão 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 botão " + 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 botão " + BotaoDois.getText() + " foi clicado"); LabelDois.setToolTipText("Esse é o label do botão dois");

(33)

public class TesteEventosBotaoELabel extends JFrame {

public TesteEventosBotaoELabel() {

addWindowListener(new WindowAdapter()

{public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(600,130);

setTitle("Botões 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. Manipulação de Botões e Labels

A figura 3.1 mostra a situação após o clique nos dois botões. No código, percebe-se que existem

duas maneiras de saber qual botão foi clicado. A primeira é testando o próprio texto do botão, a

partir do

getActionCommand().equals(). A segunda é através da definição de um objeto origem, que, através do método getSource(), sabe qual botão 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, além de utilizar o método setToolTipText()

para especificar a dica de ferramenta, que é exibida quando o cursor do mouse passa sobre o

label.

3.2 Botões de Estado – Classes JRadioButton e JCheckBox

Os botões de estado permitem ativar ou desativar opções. Dois tipos são comumente usados: as

caixas de seleção e os botões de rádio. Uma caixa de seleção possui um rótulo (label) que a

identifica e, ao clicar nela, a opção vai ficar ativada ou não, conforme o estado atual. Botões de

rádio ficam agrupados a partir da classe ButtonGroup, sendo que apenas uma opção pode ficar

selecionada. Para tratamento dos eventos, a interface utilizada é a

ActionListener, como nos

botões e caixas de texto. Exemplo:

import java.awt.*;

(34)

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 visualização",15); CBItalico = new JCheckBox("Itálico");

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";

(35)

} }

public class BotoesDeEstado extends JFrame {

public BotoesDeEstado() {

addWindowListener(new WindowAdapter()

{public void windowClosing(WindowEvent e){System.exit(0);}}); setSize(350,100);

setTitle("Botões 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. Botões de Estado

A figura 3.2 apresenta o resultado da execução do exemplo, já com alguns itens selecionados. Ao

clicar em uma caixa de seleção, é acionado um evento de ação, capturado no método

actionPerformed(). O método isSelect() retorna o estado atual da caixa de seleção e,

conforme o estado, as variáveis

Italico e Negrito são atualizadas, para depois servirem de

parâmetro para a alteração da fonte a partir do

setFont(). Os botões de rádio são criados, já

tendo setado qual é o botão que ficará selecionado inicialmente. Cada um desses botões deve ser

adicionado a um grupo de botões (ButtonGroup), sendo ele responsável pala desativação do

botão anteriormente selecionado, quando um novo for clicado. No

actionPerformed() é

verificado qual botão originou o evento, e a variável Fonte é atualizada com a fonte atual, para

também servir de parâmetro no setFont(). Isso é feito através da criação de um objeto f, do tipo

Font, incializado a partir do getFont() e passado para a variável Fonte através do getName().

3.3 Bordas

O Swing oferece várias opções de bordas para melhorar o aspecto visual da aplicação. O método

setBorder(), da classe JComponent, é a responsável pela definição das bordas, recebendo como

parâmetro um objeto de uma das classes de bordas existentes no pacote javax.swing.border.

Por isso, é necessário realizar um

import desse pacote. O exemplo a seguir mostra as diversas

bordas existentes, permitindo a utilização de título ou não.

import java.awt.*;

(36)

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) {

(37)

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 Título "); 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); }

}

(38)

A figura 3.3 mostra o resultado da execução, onde cada um dos botões realiza a mudança para a

borda especificada. O título na borda somente é mostrado se a caixa de seleção

Titled estiver

marcada.

De forma geral, para criar uma borda é necessário criar um objeto

Border e utilizar um dos

métodos da classe

BorderFactory para criar a borda desejada. Os tipos de borda existentes, os

métodos para criação, o parâmetros necessários em cada tipo e as variações possíveis são:

EtchedBorder: cria uma borda de linha com efeito 3D.

createEtchedBorder()

createEtchedBorder(Color destaque, Color Sombra)

EmptyBorder: cria uma borda vazia, mas ocupa espaço e permite inserção de título.

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 sólida 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 título. Normalmente é utilizado para inserir títulos

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 posição, Font fonte, Color cor)

O alinhamento do

TitledBorder pode ser uma das constantes: TitledBorder.LEFT, TitledBorder.RIGHT ou TitledBorder.CENTER. A posição pode ser uma das constantes de TitledBorder: ABOVE_TOP, TOP, BELOW_TOP, ABOVE_BOTTOM, BOTTOM, BELOW_BOTTOM.

3.4 Caixas de Combinação

Imagem

Figura 1.7. Frame Fontes
Figura 1.8. Frame Imagens
Figura 1.9. Contêiner do tipo painel
Figura 1.12. Gerenciador de Layout GridLayout
+7

Referências

Documentos relacionados

Imaginemos o problema que seria, se os Espíritos chegassem lá, plano mais feliz e consequentemente com muito mais beleza que a esfera material da Terra e ficassem sem saber qual

•   O  material  a  seguir  consiste  de  adaptações  e  extensões  dos  originais  gentilmente  cedidos  pelo 

através da criação de condições para atrair investigadores/cientistas de mérito internacional, do desenvolvimento do pólo tecnológico e de parcerias com instituições nacionais

As transações comerciais – exportações mais importações – brasileiras de cosméticos, perfumaria e artigos de higiene pessoal são concentradas na União Européia (32%, em

Transformar los espacios es también transformar la dinámica de las relaciones dentro del ambiente de trabajo, la glo- balización alteró el mundo corporativo, en ese sentido es

O enfermeiro, como integrante da equipe multidisciplinar em saúde, possui respaldo ético legal e técnico cientifico para atuar junto ao paciente portador de feridas, da avaliação

Seja o operador linear tal que. Considere o operador identidade tal que. Pela definição de multiplicação por escalar em transformações lineares,. Pela definição de adição

O mercado externo também se equilibra pelo balanço de pagamentos, ou seja, pelo balanço entre as transações correntes (bens e serviços) e o mercado de capitais (ativos