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.
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
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.
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);
} }
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, controlandocores, 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 sersobrescrito 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 noexemplo 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);
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)
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); }
}
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 umaaltura 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 seutamanho. 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); }
}
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 comoresultado 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);
}
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): Desenhaum 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 preenchea 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.
•
drawPolygon(int[] xPoints, int[] yPoints, int nPoints): Desenha umpolí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 amaneira 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);
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 oconteú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 daimagem, 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() {
{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 automaticamentetoda 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) fazcom 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 deconteú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, ogerenciador 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.
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 layoutatravé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));
O
GridLayout é um gerenciador que organiza os componentes em linhas e colunas espaçadasregularmente. 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
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 emlocais 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);
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 criarbarras 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()); }
}
{
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çamentovariável, conforme o tamanho da janela e o
createHorizontalStrut(), que determina umespaç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 devemestar 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.
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) {
} }
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. Oscampos 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.
número de linhas) e largura (em número de colunas) através dos campos
gridwidthe
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;
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
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, dandomuita 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);
} }
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 dopainel com layout
BorderLayout. Isso é uma prática bastante comum para se alcançar layoutscom 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 outraslocalizações se a do centro estiver vazia.
2. Interface Gráfica com o Usuário e a Manipulação de Eventos
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 asimplementarem. Além disso, “todos” os métodos
abstract devem ser redefinidos. O registrodesses 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 {
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);
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 umEnter 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() {
{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.MacLookAndFeelLogo após, é necessário chamar o método
SwingUtilities.updateComponentTreeUIpara
atualizar todo o conjunto de componentes.
import java.awt.*;
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 {
{
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
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
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 emlabels, 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");
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 posicionamentohorizontal (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 nosbotões e caixas de texto. Exemplo:
import java.awt.*;
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";
} }
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 deparâ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 comoparâ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 diversasbordas existentes, permitindo a utilização de título ou não.
import java.awt.*;
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) {
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); }
}
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 estivermarcada.
De forma geral, para criar uma borda é necessário criar um objeto
Border e utilizar um dosmétodos da classe
BorderFactory para criar a borda desejada. Os tipos de borda existentes, osmé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)