5. Interfaces gráficas
Propomos aqui mostrar como construir interfaces gráficas com JAVA. Primeiramente, veremos quais são as classes básicas que nos permitem construir uma interface gráfica. Inicialmente, não utilizaremos nenhuma ferramenta de geração automática. Em seguida, utilizaremos o JBuilder, uma ferramenta de desenvolvimento da Borland/Inprise que facilita o desenvolvimento de aplicativos Java e, em especial, a construção de interfaces gráficas.
5.1. Noções básicas sobre interfaces gráficas
5.1.1. Uma janela simples
Consideremos o código a seguir:
// classes importadas
import javax.swing.*;
import java.awt.*;
// a classe do formulário
public class form1 extends JFrame {
// o construtor
public form1() {
// título da janela
this.setTitle("Mon premier formulaire");
// dimensões da janela
this.setSize(new Dimension(300,100));
}//construtor
// função de teste
public static void main(String[] args) {
// o formulário é exibido
new form1().setVisible(true);
}
}//classe
A execução do código anterior exibe a seguinte janela:

Uma interface gráfica geralmente deriva da classe base JFrame:
public class form1 extends JFrame {
A classe base JFrame define uma janela básica com botões para fechar, ampliar/reduzir, tamanho ajustável etc. e gerencia os eventos nesses objetos gráficos. Aqui, especializamos a classe base definindo um título, a largura (300 pixels) e a altura (100 pixels). Isso é feito em seu construtor:
// o construtor
public form1() {
// título da janela
this.setTitle("Mon premier formulaire");
// dimensões da janela
this.setSize(new Dimension(300,100));
}//construtor
O título da janela é definido pelo método setTitle e suas dimensões pelo método setSize. Esse método aceita como parâmetro um objeto Dimension(largeur,hauteur), em que largeur e hauteur representam a largura e a altura da janela, expressas em pixels.
O método main inicia o aplicativo gráfico da seguinte maneira:
new form1().setVisible(true);
Um formulário do tipo form1 é então criado (new form1()) e exibido (setVisible(true)), e, em seguida, o aplicativo fica à espera dos eventos que ocorrem no formulário (cliques, movimentos do mouse, ...) e executa aqueles que o formulário suporta. Neste caso, nosso formulário não suporta outros eventos além daqueles gerenciados pela classe base JFrame (cliques nos botões de fechar, ampliar/reduzir, alteração do tamanho da janela, movimentação da janela, etc.).
Ao testar este programa, executando-o a partir de uma janela do DOS com o comando:
para executar o arquivo form1.class, percebe-se que, ao fechar a janela exibida, o controle não volta para a janela do DOS, como se o programa não tivesse sido concluído. De fato, é esse o caso. A execução do programa ocorre da seguinte maneira:
- inicialmente, é iniciado um primeiro thread de execução para executar o método main
- quando este cria o formulário e o exibe, uma segunda thread é criada para gerenciar especificamente os eventos relacionados ao formulário
- após essa criação e, no nosso exemplo, o thread do método main é encerrado, restando apenas o thread de execução da interface gráfica.
- Quando a janela é fechada, ela desaparece, mas não interrompe a thread na qual estava sendo executada
- Por enquanto, somos obrigados a interromper esse thread pressionando Ctrl-C na janela do DOS a partir da qual a execução do programa foi iniciada.
Vamos verificar a existência de duas threads separadas: uma na qual é executado o método main e outra na qual é executada a janela gráfica:
// classes importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
// a classe do formulário
public class form1 extends JFrame {
// o construtor
public form1() {
// título da janela
this.setTitle("Mon premier formulaire");
// dimensões da janela
this.setSize(new Dimension(300,100));
}//construtor
// função de teste
public static void main(String[] args) {
// acompanhamento
System.out.println("Début du thread main");
// exibe o formulário
new form1().setVisible(true);
// acompanhamento
System.out.println("Fin du thread main");
}//principal
}//classe
A execução produz os seguintes resultados:

Pode-se observar que o thread main foi encerrado, embora a janela ainda esteja exibida. Fechar a janela não encerra o thread no qual ela estava sendo executada. Para interromper esse thread, pressione novamente Ctrl-C na janela do DOS.
Para concluir este exemplo, observemos os pacotes importados:
- javax.swing para a classe JFrame
- java.awt para a classe Dimension
5.1.2. Gerenciando um evento
No exemplo anterior, precisaríamos gerenciar o fechamento da janela por conta própria para que, quando isso ocorresse, a aplicação fosse encerrada, o que, por enquanto, não está sendo feito. Para isso, precisamos criar um objeto que “escute” os eventos que ocorrem na janela e detecte o evento “fechamento da janela”. Esse objeto é chamado de “listener” ou gerenciador de eventos. Existem diferentes tipos de gerenciadores para os diversos eventos que podem ocorrer nos componentes de uma interface gráfica. Para o componente JFrame, o listener é chamado de WindowListener e é uma interface que define os seguintes métodos (consulte a documentação Java)
Resumo dos métodos | ||
void | windowActivated(WindowEvent e) A janela passa a ser a janela ativa | |
void | windowClosed(WindowEvent e) A janela foi fechada | |
void | windowClosing(WindowEvent e) O usuário ou o programa solicitou o fechamento da janela | |
void | windowDeactivated(WindowEvent e) A janela não é mais a janela ativa | |
void | windowDeiconified(WindowEvent e) A janela passa do estado minimizado para o estado normal | |
void | windowIconified(WindowEvent e) A janela passa do estado normal para o estado minimizado | |
void | windowOpened(WindowEvent e) A janela torna-se visível pela primeira vez | |
Portanto, há sete eventos que podem ser tratados. Todos os manipuladores recebem como parâmetro um objeto do tipo WindowEvent, que ignoraremos por enquanto. O evento que nos interessa aqui é o fechamento da janela, evento que deverá ser tratado pelo método windowClosing. Para tratar esse evento, podemos criar um objeto Windowlistener por meio de uma classe anônima da seguinte maneira:
// criação de um gerenciador de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definição do Windows
Nosso gerenciador de eventos que implementa a interface WindowListener deve definir os sete métodos dessa interface. Como queremos gerenciar apenas o fechamento da janela, definiremos código apenas para o método windowClosing. Quando os outros eventos ocorrerem, seremos notificados, mas não faremos nada. O que faremos quando formos notificados de que a janela está sendo fechada (windowClosing)? Encerraremos o aplicativo:
public void windowClosing(WindowEvent e){System.exit(0);}
Temos aqui um objeto capaz de gerenciar os eventos de uma janela em geral. Como associá-lo a uma janela específica? A classe JFrame possui um método addWindowListener(WindowListener win) que permite associar um gerenciador de eventos “janela” a uma janela específica. Assim, aqui, no construtor da janela, escreveremos:
// criação de um gerenciador de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definição do Windows
// este gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win);
A programação completa é a seguinte:
// classes importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// a classe do formulário
public class form2 extends JFrame {
// o construtor
public form2() {
// título da janela
this.setTitle("Mon premier formulaire");
// dimensões da janela
this.setSize(new Dimension(300,100));
// criação de um gerenciador de eventos
WindowListener win=new WindowListener(){
public void windowActivated(WindowEvent e){}
public void windowClosed(WindowEvent e){}
public void windowClosing(WindowEvent e){System.exit(0);}
public void windowDeactivated(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowIconified(WindowEvent e){}
public void windowOpened(WindowEvent e){}
};//definição do Windows
// este gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win);
}//construtor
// função de teste
public static void main(String[] args) {
// exibimos o formulário
new form2().setVisible(true);
}//main
}//classe
O pacote java.awt.event contém a interface WindowListener. Ao executar esse programa e fechar a janela exibida, observa-se na janela do DOS, onde o programa foi iniciado, o término da execução do programa, o que não acontecia anteriormente.
Em nosso programa, a criação do objeto responsável por gerenciar os eventos da janela é um pouco complicada, na medida em que somos obrigados a definir métodos mesmo para eventos que não queremos gerenciar. Nesse caso, em vez de usar a interface WindowListener, podemos usar a classe WindowAdapter. Ela implementa a interface WindowListener, com sete métodos vazios. Ao derivar a classe WindowAdapter e redefinir apenas os métodos que nos interessam, chegamos ao mesmo resultado que com a interface WindowListener, mas sem precisar definir os métodos que não nos interessam. A sequência
- de definição do gerenciador de eventos
- associação do manipulador à janela
pode ser realizada da seguinte maneira em nosso exemplo:
// criação de um gerenciador de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definição do Windows
// esse gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win);
Aqui, utilizamos uma classe anônima que deriva da classe WindowAdapter e redefine seu método windowClosing. O programa fica então assim:
// classes importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// a classe do formulário
public class form2 extends JFrame {
// o construtor
public form2() {
// título da janela
this.setTitle("Mon premier formulaire");
// dimensões da janela
this.setSize(new Dimension(300,100));
// criação de um gerenciador de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definição do Windows
// este gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win); }//construtor
// função de teste
public static void main(String[] args) {
// exibimos o formulário
new form2().setVisible(true);
}//main
}//classe
Ele produz os mesmos resultados que o programa anterior, mas é mais simples de escrever.
5.1.3. Um formulário com botão
Vamos agora adicionar um botão à nossa janela:
// classes importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// a classe do formulário
public class form3 extends JFrame {
// um botão
JButton btnTest=null;
Container conteneur=null;
// o construtor
public form3() {
// título da janela
this.setTitle("Formulaire avec bouton");
// dimensões da janela
this.setSize(new Dimension(300,100));
// criação de um gerenciador de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definição do Windows
// esse gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win);
// recuperamos o contêiner da janela
conteneur=this.getContentPane();
// escolhe-se um gerenciador de formatação dos componentes nesse contêiner
conteneur.setLayout(new FlowLayout());
// cria-se um botão
btnTest=new JButton();
// define-se o texto do botão
btnTest.setText("Test");
// adiciona-se o botão ao contêiner
conteneur.add(btnTest);
}//construtor
// função de teste
public static void main(String[] args) {
// exibe-se o formulário
new form3().setVisible(true);
}//main
}//classe
Uma janela JFrame possui um contêiner no qual é possível inserir componentes gráficos (botões, caixas de seleção, listas suspensas, etc.). Esse contêiner está disponível por meio do método getContentPane da classe JFrame:
Container conteneur=null;
..........
// recupera-se o contêiner da janela
conteneur=this.getContentPane();
Todo componente é inserido no contêiner pelo método add da classe Container. Assim, para inserir o componente C no objeto conteneur anterior, escrever-se-á:
Onde esse componente é colocado no contêiner? Existem diversos gerenciadores de layout de componentes com o nome XXXLayout, sendo que XXX é igual, por exemplo, a Border, Flow, ... Cada gerenciador de layout tem suas particularidades. Por exemplo, o gerenciador FlowLayout dispõe os componentes em linha, começando pela parte superior do formulário. Quando uma linha é preenchida, os componentes são colocados na linha seguinte. Para associar um gerenciador de formatação a uma janela JFrame, utiliza-se o método setLayout da classe JFrame da seguinte forma:
Assim, em nosso exemplo, para associar um gerenciador do tipo FlowLayout à janela, escrevemos:
// escolhe-se um gerenciador de formatação dos componentes nesse contêiner
conteneur.setLayout(new FlowLayout());
É possível não utilizar um gerenciador de layout e escrever:
Nesse caso, será necessário fornecer as coordenadas precisas do componente no contêiner na forma (x, y, largura, altura), em que (x, y) são as coordenadas do canto superior esquerdo do componente no contêiner. É esse método que utilizaremos com mais frequência daqui em diante.
Agora sabemos como os componentes são posicionados no contêiner (add) e onde (setLayout). Resta saber quais
componentes que podem ser colocados em um contêiner. Aqui, colocamos um botão modelado pela classe javax.swing.JButton:
JButton btnTest=null;
..........
// cria-se um botão
btnTest=new JButton();
// define-se o texto do botão
btnTest.setText("Test");
// adiciona-se o botão ao contêiner
conteneur.add(btnTest);
Ao testar este programa, obtém-se a seguinte janela:

Se redimensionarmos o formulário acima, o gerenciador de layout do contêiner é chamado automaticamente para reposicionar os componentes:

Esse é o principal benefício dos gerenciadores de layout: manter um layout coerente dos componentes à medida que o tamanho do contêiner é alterado. Vamos usar o gerenciador de layout null para ver a diferença. O botão agora é posicionado no contêiner pelas seguintes instruções:
// seleciona-se um gerenciador de formatação de componentes neste contêiner
conteneur.setLayout(null);
// cria-se um botão
btnTest=new JButton();
// define-se o texto do botão
btnTest.setText("Test");
// define-se sua posição e suas dimensões
btnTest.setBounds(10,20,100,20);
// adiciona-se o botão ao contêiner
conteneur.add(btnTest);
Aqui, posicionamos explicitamente o botão no ponto (10,20) do formulário e definimos suas dimensões como 100 pixels de largura e 20 pixels de altura. A nova janela fica assim:

Se redimensionarmos a janela, o botão permanece no mesmo lugar.

Se clicarmos no botão Test, nada acontece. De fato, ainda não associamos nenhum manipulador de eventos ao botão. Para saber quais tipos de manipuladores de eventos estão disponíveis para um determinado componente, pode-se procurar na definição de sua classe os métodos addXXXListener que permitem associar um manipulador de eventos ao componente. A classe javax.swing.JButton deriva da classe javax.swing.AbstractButton, na qual se encontram os seguintes métodos:
Resumo dos métodos | ||
void | addActionListener(ActionListener l) | |
void | addChangeListener(ChangeListener l) | |
void | addItemListener(ItemListener l) | |
Aqui, é preciso consultar a documentação para saber qual gerenciador de eventos lida com o clique no botão. Trata-se da interface ActionListener. Ela define apenas um método:
Resumo do método | ||
void | actionPerformed(ActionEvent e) | |
O método recebe um parâmetro ActionEvent, que ignoraremos por enquanto. Para lidar com o clique no botão btntest do nosso programa, primeiro associamos a ele um manipulador de eventos:
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//classe anônima
);//manipulador de eventos
Aqui, o método actionPerformed remete ao método btnTest_clic, que definimos da seguinte maneira:
public void btnTest_clic(ActionEvent evt){
// monitoramento do console
System.out.println("clic sur bouton");
}//btnTest_click
Sempre que o usuário clica no botão Test, uma mensagem é exibida no console. É o que mostra a execução a seguir:

O programa completo é o seguinte:
// classes importadas
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
// a classe do formulário
public class form4 extends JFrame {
// um botão
JButton btnTest=null;
Container conteneur=null;
// o construtor
public form4() {
// título da janela
this.setTitle("Formulaire avec bouton");
// dimensões da janela
this.setSize(new Dimension(300,100));
// criação de um gerenciador de eventos
WindowAdapter win=new WindowAdapter(){
public void windowClosing(WindowEvent e){System.exit(0);}
};//definição do Windows
// esse gerenciador de eventos irá gerenciar os eventos da janela atual
this.addWindowListener(win);
// recuperamos o contêiner da janela
conteneur=this.getContentPane();
// escolhe-se um gerenciador de formatação dos componentes nesse contêiner
conteneur.setLayout(null);
// cria-se um botão
btnTest=new JButton();
// define-se o texto do botão
btnTest.setText("Test");
// define-se sua posição e suas dimensões
btnTest.setBounds(10,20,100,20);
// associa-se a ele um gerenciador de eventos
btnTest.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt){
btnTest_clic(evt);
}
}//classe anônima
);//manipulador de eventos
// adiciona-se o botão ao contêiner
conteneur.add(btnTest);
}//construtor
public void btnTest_clic(ActionEvent evt){
// rastreamento por console
System.out.println("clic sur bouton");
}//btnTest_click
// função de teste
public static void main(String[] args) {
// exibição do formulário
new form4().setVisible(true);
}//principal
}//classe
5.1.4. Os gerenciadores de eventos
Os principais componentes do Swing que apresentaremos são as janelas (JFrame), os botões (JButton), as caixas de seleção (JCheckBox), botões de opção (JButtonRadio), listas suspensas (JComboBox), listas (JList), controles deslizantes (JScrollBar), rótulos (JLabel), campos de entrada de uma linha (JTextField) ou de várias linhas (JTextArea), menus (JMenuBar), os itens de menu (JMenuItem).
As tabelas a seguir apresentam uma lista de alguns gerenciadores de eventos e os eventos aos quais estão vinculados.
Gerenciador | Componente(s) | Método de registro | Evento |
ActionListener | JButton, JCheckbox, JButtonRadio, JMenuItem | public void addActionListener(ActionListener) | clique no botão, na caixa de seleção, no botão de opção ou no item de menu |
JTextField | |||
ItemListener | JComboBox, JList | public void addItemListener(ItemListener) | O elemento selecionado foi alterado |
InputMethodListener | JTextField, JTextArea | public void addMethodInputListener(InputMethodListener) | o texto do campo de entrada foi alterado ou o cursor de entrada mudou de posição |
CaretListener | JTextField, JTextArea | public void addcaretListener(CaretListener) | O cursor de entrada mudou de posição |
AdjustmentListener | JScrollBar | public void addAdjustmentListener(AdjustmentListener) | o valor do variador mudou |
MouseMotionListener | public void addMouseMotionListener(MouseMotionListener) | o mouse se moveu | |
WindowListener | JFrame | public void addWindowlistener(WindowListener) | evento de janela |
MouseListener | public void addMouselistener(MouseListener) | eventos do mouse (clique, entrada/saída da área de um componente, botão pressionado, soltar) | |
FocusListener | public void addFocuslistener(FocusListener) | evento focus (ganho, perdido) | |
KeyListener | public void addKeylistener(KeyListener) | evento de teclado (tecla digitada, pressionada, solta) |
Componente | Método de registro de manipuladores de eventos |
JButton | public void addActionListener(ActionListener) |
JCheckbox | public void addItemListener(ItemListener) |
JCheckboxMenuItem | public void addItemListener(ItemListener) |
JComboBox | public void addItemListener(ItemListener) public void addActionListener(ActionListener) |
Container | public void addContainerListener(ContainerListener) |
JComponent | public void addComponentListener(ComponentListener) public void addFocusListener(FocusListener) public void addKeyListener(KeyListener) public void addMouseListener(MouseListener) public void addMouseMotionListener(MouseMotionListener) |
JFrame | public void addWindowlistener(WindowListener) |
JList | public void addItemListener(ItemListener) |
JMenuItem | public void addActionListener(ActionListener) |
JPanel | como Container |
JScrollPane | como Container |
JScrollBar | public void addAdjustmentListener(AdjustmentListener) |
JTextComponent | public void addInputMethodListener(InputMethodListener) public void addCaretListener(CaretListener) |
JTextArea | comme JTextComponent |
JTextField | como JTextComponent public void addActionListener(ActionListener) |
Todos os componentes, exceto aqueles do tipo TextXXX, por serem derivados da classe JComponent, também possuem os métodos associados a essa classe.
5.1.5. Os métodos dos gerenciadores de eventos
A tabela a seguir lista os métodos que os diversos gerenciadores de eventos devem implementar.
Interface | Métodos |
ActionListener | public void actionPerformed(ActionEvent) |
AdjustmentListener | public void adjustmentValueChanged(AdjustmentEvent) |
ComponentListener | public void componentHidden(ComponentEvent) public void componentMoved(ComponentEvent) public void componentResized(ComponentEvent) public void componentShown(ComponentEvent) |
ContainerListener | public void componentAdded(ContainerEvent) public void componentRemoved(ContainerEvent) |
FocusListener | public void focusGained(FocusEvent) public void focusLost(FocusEvent) |
ItemListener | public void itemStateChanged(ItemEvent) |
KeyListener | public void keyPressed(KeyEvent) public void keyReleased(KeyEvent) public void keyTyped(KeyEvent) |
MouseListener | public void mouseClicked(MouseEvent) public void mouseEntered(MouseEvent) public void mouseExited(MouseEvent) public void mousePressed(MouseEvent) public void mouseReleased(MouseEvent) |
MouseMotionListener | public void mouseDragged(MouseEvent) public void mouseMoved(MouseEvent) |
TextListener | public void textValueChanged(TextEvent) |
InputmethodListener | public void InputMethodTextChanged(InputMethodEvent) public void caretPositionChanged(InputMethodEvent) |
CaretLisetner | public void caretUpdate(CaretEvent) |
WindowListener | public void windowActivated(WindowEvent) public void windowClosed(WindowEvent) public void windowClosing(WindowEvent) public void windowDeactivated(WindowEvent) public void windowDeiconified(WindowEvent) public void windowIconified(WindowEvent) public void windowOpened(WindowEvent) |
5.1.6. As classes adaptadoras
Como vimos na interface WindowListener, existem classes denominadas XXXAdapter que implementam as interfaces XXXListener com métodos vazios. Um manipulador de eventos derivado de uma classe XXXAdapter pode, então, implementar apenas uma parte dos métodos da interface XXXListener, aqueles de que o aplicativo necessita.
Suponhamos que se queira gerenciar os cliques do mouse em um componente Frame f1. Seria possível associar a ele um manipulador de eventos da seguinte forma:
e escrever:
public class gestionnaireSouris implements MouseListener{
// escrevendo os 5 métodos da interface MouseListener
// mouseClicked, ..., mouseReleased)
}// fim da classe
Como queremos lidar apenas com os cliques do mouse, é preferível escrever:
public class gestionnaireSouris extends MouseAdapter{
// escrevemos apenas um método, aquele que gerencia os cliques do mouse
public void mouseClicked(MouseEvent evt){
…
}
}// fim da classe
A tabela a seguir apresenta as classes adaptadoras dos diferentes gerenciadores de eventos:
Gerenciador de eventos | Adaptador |
ComponentListener | ComponentAdapter |
ContainerListener | ContainerAdapter |
FocusListener | FocusAdapter |
KeyListener | KeyAdapter |
MouseListener | MouseAdapter |
MouseMotionListener | MouseMotionAdapter |
WindowListener | WindowAdapter |
5.1.7. Conclusão
Acabamos de apresentar os conceitos básicos da criação de interfaces gráficas em Java:
- criação de uma janela
- criação de componentes
- associação dos componentes à janela por meio de um gerenciador de layout
- associação de manipuladores de eventos aos componentes
Agora, em vez de construir interfaces gráficas “manualmente”, como acabamos de fazer, vamos usar o JBuilder, uma ferramenta de desenvolvimento Java da Borland/Inprise na versão 4, e supérieure.Nous utilizaremos os componentes da biblioteca java.swing, atualmente recomendada pela Sun, criadora do Java.
5.2. Criando uma interface gráfica com o JBuilder
5.2.1. Nosso primeiro projeto no JBuilder
Para nos familiarizarmos com o JBuilder, vamos criar um aplicativo bem simples: uma janela vazia.
- Inicie o JBuilder e selecione a opção Arquivo/Novo projeto. A primeira página de um assistente será exibida:

- Preencha os seguintes campos:
Nome do projeto | Início Isso criará um arquivo de projeto début.jpr na pasta indicada no campo “Nome da pasta do projeto” |
Caminho raiz | indique a pasta na qual será criada a pasta do projeto que você vai criar. |
Nome da pasta do projeto | indique o nome da pasta onde serão colocados todos os arquivos do projeto. Essa pasta será criada na pasta indicada no campo “Caminho raiz” |
Os arquivos de origem (.java, .html, ...), os arquivos de destino (.class, ...) e os arquivos de backup podem ser colocados em diretórios diferentes. Se você deixar esses campos em branco, eles serão colocados no mesmo diretório do projeto.
Execute [suivant]
- Uma tela confirma as opções da etapa anterior

Execute [suivant]
- Uma nova tela solicita que você defina as características do seu projeto:

Execute [terminer]
- Verifique se a opção Voir/projet está marcada. Você deverá ver a estrutura do seu projeto na janela à esquerda.

- Agora vamos criar uma interface gráfica neste projeto. Escolha a opção Fichier/Nouveau/Application:

No campo classe, insira o nome da classe que será criada. Aqui, usamos o mesmo nome do projeto.
Execute [suivant]
- A tela a seguir é exibida:

Classe | interfaceDébut Este é o nome da classe correspondente à janela que será criada |
Título | Este é o texto que aparecerá na barra de título da janela |
Observe que, acima, solicitamos que a janela seja centralizada na tela ao iniciar o aplicativo.
Crie [Terminer]
- É agora que o JBuilder se mostra útil.
- Ele gera os arquivos-fonte .java das duas classes cujos nomes foram fornecidos: a classe do aplicativo e a da interface gráfica. Esses dois arquivos aparecem na estrutura do projeto, na janela à esquerda

- Para acessar o código gerado para as duas classes, basta clicar duas vezes no arquivo .java correspondente. Voltaremos ao código gerado posteriormente.
- Verifique se a opção Voir/Structure está marcada. Ela permite visualizar a estrutura da classe atualmente selecionada (clique duplo no arquivo .java). Aqui está, por exemplo, a estrutura da classe début:

Aqui, aprendemos:
-
as bibliotecas importadas (imports)
-
que existe um construtor début()
-
que existe um método estático main()
-
que existe um atributo packFrame
Qual é a vantagem de ter acesso à estrutura de uma classe?
-
você tem uma visão geral dela. Isso é útil se sua classe for complexa.
-
você pode acessar o código de um método clicando nele na janela de estrutura da classe. Mais uma vez, isso é útil se sua classe tiver centenas de linhas. Você não precisa percorrer todas as linhas para encontrar o código que está procurando.
O código gerado pelo JBuilder já está pronto para uso. Selecione Executar/Executar o projeto ou F9 e você verá a janela solicitada:

Além disso, ela se fecha corretamente quando clicamos no botão de fechar da janela. Acabamos de criar nossa primeira interface gráfica. Podemos salvar nosso projeto pela opção Arquivo/Fechar projetos:

Ao pressionar Tous, todos os projetos presentes na janela acima serão marcados. OK os fechará. Se quisermos dar uma olhada, usando o Explorador do Windows, na pasta do nosso projeto (aquela que foi indicada ao assistente no início da configuração do projeto), encontraremos os seguintes arquivos:

No nosso exemplo, solicitamos que todos os arquivos (fonte .java, destino .class, cópia de segurança .jpr~) ficassem na mesma pasta que o projeto .jpr.
5.2.2. Os arquivos gerados pelo JBuilder para uma interface gráfica
Vamos agora dar uma olhada nos arquivos-fonte .java gerados pelo JBuilder. É importante saber interpretar o que foi gerado, já que, na maioria das vezes, precisamos adicionar código ao que foi gerado. Comecemos recuperando nosso projeto: Arquivo/Abrir um projeto e selecionemos o projeto début.jpr. Encontramos o projeto criado anteriormente.
5.2.2.1. A classe principal
Vamos examinar a classe début.java clicando duas vezes em seu nome na janela que exibe a lista de arquivos do projeto. Temos o seguinte código:
import javax.swing.UIManager;
import java.awt.*;
public class début {
boolean packFrame = false;
/**Compilar o aplicativo*/
public début() {
interfaceDébut frame = new interfaceDébut();
//Validar os quadros com tamanhos predefinidos
//Compactar os quadros com informações de tamanho preferencial — por exemplo, a partir de seu layout
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Centralizar a janela
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
/**Método principal*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new début();
}
}
Vamos comentar o código gerado:
- a função main define a aparência da janela (setLookAndFeel) e cria uma instância da classe début.
- O construtor début() é então executado. Ele cria uma instância frame da classe da janela (new interfaceDébut()). Essa instância é construída, mas não exibida.
- A janela é então dimensionada de acordo com as informações disponíveis para cada um dos componentes da janela (frame.validate). Ela então inicia sua existência independente, sendo exibida e respondendo às solicitações do usuário.
- A janela é centralizada na tela, pois isso foi solicitado durante a configuração da janela com o assistente.
Vamos ver o que seria obtido se reduzíssemos o código début.java ao seu mínimo necessário, como fizemos no início do capítulo. Vamos criar uma nova classe. Selecione a opção Arquivo/Nova classe:

Nomeie a nova classe como début2 e renomeie a anterior para [Terminer]. Um novo arquivo aparece no projeto:

O arquivo début2.java é reduzido à sua forma mais simples:
Vamos completar a classe da seguinte maneira:
public class début2 {
// função principal
public static void main(String args[]){
// cria a janela
new interfaceDébut().show(); // ou new interfaceDébut.setVisible(true);
}//main
}//classe início2
A função main cria uma instância da janela interfaceDébut e a exibe (show). Antes de executar nosso projeto, é preciso observar que a classe que contém a função main a ser executada agora é a classe début2. Clique com o botão direito do mouse no projeto début.jpr e selecione a opção propriétés e, em seguida, a guia Exécution:
21

Aqui, está indicado que a classe principal é début (1). Clique no botão (2) para selecionar outra classe principal:

Selecione début2 e altere para [OK].

Digite [OK] para confirmar essa escolha e, em seguida, solicite a execução do projeto por meio de Executar/Executar projeto ou F9. Você obtém a mesma janela que com a classe début, exceto que ela não está centralizada, já que isso não foi solicitado neste caso. Daqui em diante, não apresentaremos mais a classe principal gerada pelo JBuilder, pois ela sempre faz a mesma coisa: criar uma janela. É na classe dessa janela que, a partir de agora, vamos nos concentrar.
5.2.2.2. A classe da janela
Vejamos agora o código que foi gerado para a classe interfaceDébut:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceDébut extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
/**Construir o quadro*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}
5.2.2.2.1. As bibliotecas importadas
Trata-se das bibliotecas java.awt, java.awt.event e javax.swing. As duas primeiras eram as únicas disponíveis para criar interfaces gráficas com as primeiras versões do Java. A biblioteca javax.swing é mais recente. Nesse caso, ela é necessária para a janela do tipo JFrame, que está sendo utilizada aqui.
5.2.2.2.2. Os atributos
JPanel é um tipo de contêiner no qual é possível inserir componentes. BorderLayout é um dos tipos de gerenciador de formatação disponíveis para posicionar os componentes no contêiner. Em todos os nossos exemplos, não utilizaremos nenhum gerenciador de formatação e colocaremos nós mesmos os componentes em um local específico do contêiner. Para isso, utilizaremos o gerenciador de formatação null.
5.2.2.2.3. O construtor da janela
/**Construir o quadro*/
public interfaceDébut() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Ma première interface graphique avec Jbuilder");
}
- O desenvolvedor começa informando que irá gerenciar os eventos na janela (enableEvents) e, em seguida, chama o método jbInit.
- O contêiner (JPanel) da janela (JFrame) é obtido (getContentPane)
- O gerenciador de formatação é definido (setLayout)
- O tamanho da janela é definido (setSize)
- O título da janela é definido (setTitle)
5.2.2.2.4. O gerenciador de eventos
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
O criador havia indicado que a classe trataria os eventos da janela. É o método processWindowEvent que realiza essa tarefa. Ela começa transmitindo à sua classe pai (JFrame) o evento WindowEvent recebido e, se este for o evento WINDOW_CLOSING provocado pelo clique no botão de fechamento da janela, o aplicativo é encerrado.
5.2.2.2.5. Conclusão
O código da classe da janela é diferente daquele apresentado no exemplo no início do capítulo. Se usássemos outra ferramenta de geração de código Java que não o JBuilder, sem dúvida teríamos um código ainda diferente. Na prática, aceitaremos o código gerado pelo JBuilder para construir a janela, a fim de nos concentrarmos exclusivamente na escrita dos manipuladores de eventos da interface gráfica.
5.2.3. Desenhando uma interface gráfica
5.2.3.1. Um exemplo
No exemplo anterior, não colocamos componentes na janela. Vamos agora construir uma janela com um botão, um rótulo e um campo de entrada:

Os campos são os seguintes:
n.º | nome | tipo | função |
1 | lblSaisie | JLabel | uma descrição |
2 | txtSaisie | JTextField | um campo de preenchimento |
3 | cmdAfficher | JButton | para exibir em uma caixa de diálogo o conteúdo do campo de entrada txtSaisie |
Seguindo o mesmo procedimento do projeto anterior, crie o projeto interface2.jpr sem inserir, por enquanto, nenhum componente na janela.

Na janela acima, selecione a classe interface2.java da janela. À direita dessa janela, há uma pasta com abas:

A aba Source dá acesso ao código-fonte da classe interface2.java. A aba Conception permite construir visualmente a janela. Selecione essa aba. Você tem diante de si o contêiner da janela, que receberá os componentes que você irá inserir nele. Por enquanto, ele está vazio. Na janela à esquerda é exibida a estrutura da classe:

this | representa a janela |
contentPane | seu contêiner, no qual serão inseridos os componentes, bem como a forma como esses componentes serão dispostos no contêiner (BorderLayout por padrão) |
borderLayout1 | uma instância do gerenciador de formatação |
Selecione o objeto this. Sua janela de propriedades será exibida à direita:

Algumas dessas propriedades merecem destaque:
background | para definir a cor de fundo da janela |
foreground | para definir a cor dos elementos na janela |
JMenuBar | para associar um menu à janela |
title | para atribuir um título à janela |
resizable | para definir o tipo de janela |
font | para definir a fonte das letras na janela |
Com o objeto this ainda selecionado, é possível redimensionar o contêiner exibido na tela arrastando os pontos de ancoragem localizados ao redor do contêiner:

Agora estamos prontos para inserir componentes no contêiner acima. Antes disso, vamos alterar o gerenciador de formatação. Selecione o objeto contentPane na janela de estrutura:

Em seguida, na janela de propriedades desse objeto, selecione a propriedade layout e escolha, entre os valores possíveis, o valor null:

A ausência de um gerenciador de formatação nos permitirá posicionar livremente os componentes no contêiner. Agora é hora de selecioná-los.
Quando o painel Conception está selecionado, os componentes ficam disponíveis em uma pasta com abas na parte superior da janela de design:

Para construir a interface gráfica, temos à disposição os componentes swing (1) e os componentes awt (2). Aqui, vamos utilizar os componentes swing. Na barra de componentes acima, selecione um componente JLabel (3), um componente JTextField (4) e um componente JButton (5) e coloque-os no contêiner da janela de design.

Agora vamos personalizar cada um desses três componentes:
- o rótulo (JLabel) jLabel1
Selecione o componente para abrir sua janela de propriedades. Nela, altere as seguintes propriedades: nome: lblSaisie, texto: Entrada
- o campo de entrada (JTextField) jTextfield1
Selecione o componente para abrir sua janela de propriedades. Nela, altere as seguintes propriedades: name: txtSaisie, text: não preencher
- o botão (JButton): nome: cmdAfficher, texto: Exibir
Agora temos a seguinte janela:

e a seguinte estrutura:

Podemos executar (F9) nosso projeto para ter uma primeira prévia da janela em ação:

Feche a janela. Resta-nos escrever o procedimento associado ao clique no botão Afficher. Selecione o botão para acessar sua janela de propriedades. Ela possui duas abas: propriétés e événements. Selecione événements.

A coluna da esquerda da janela lista os eventos possíveis para o botão. Um clique no botão corresponde ao evento actionPerformed. A coluna da direita contém o nome do procedimento chamado quando o evento correspondente ocorre. Clique na célula à direita do evento actionPerformed:

O JBuilder gera um nome padrão para cada manipulador de evento no formato nomComposant_nomEvénement, como neste caso: cmdAfficher_actionPerformed. É possível apagar o nome proposto por padrão e inserir outro. Para acessar o código do manipulador cmdAfficher_actionPerformed, basta clicar duas vezes em seu nome acima. Assim, o sistema passa automaticamente para o painel de código-fonte da classe, posicionado no esboço do código do manipulador de eventos:
Resta apenas preencher esse código. Aqui, queremos exibir uma caixa de diálogo com o conteúdo do campo txtSaisie:
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(),
"Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
JOptionPane é uma classe da biblioteca javax.swing. Ela permite exibir mensagens acompanhadas de um ícone ou solicitar informações ao usuário. Aqui, utilizamos um método estático da classe:

parentComponent | o objeto contêiner “pai” da caixa de diálogo: neste caso, this. |
mensagem | um objeto a ser exibido. Aqui, o conteúdo do campo de entrada |
title | o título da caixa de diálogo |
messageType | o tipo da mensagem a ser exibida. Determina o ícone que será exibido na caixa ao lado da mensagem. Os valores possíveis: INFORMATION_MESSAGE, QUESTION_MESSAGE, ERROR_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE |
Vamos executar nosso aplicativo (F9):


5.2.3.2. O código da classe da janela
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import javax.swing.event.*;
public class interface2 extends JFrame {
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
/**Construir o quadro*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.3.2.1. Os atributos
JPanel contentPane;
JLabel lblSaisie = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmdAfficher = new JButton();
Encontramos o contêiner dos componentes do tipo JPanel e os três componentes.
5.2.3.2.2. O fabricante
/**Construir o quadro*/
public interface2() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}
O construtor interface2 é semelhante ao construtor da interface gráfica analisada anteriormente. É no método jbInit que encontramos as diferenças: o código de construção da janela depende dos componentes que foram colocados nela. Podemos reutilizar o código de jbInit, acrescentando nossos próprios comentários:
private void jbInit() throws Exception {
// a própria janela (tamanho, título)
this.setSize(new Dimension(304, 129));
this.setTitle("Saisies & boutons - 1");
// o contêiner dos componentes
contentPane = (JPanel) this.getContentPane();
// nenhum gerenciador de formatação para este contêiner
contentPane.setLayout(null);
// o rótulo lblSaisie (texto, posição, tamanho)
lblSaisie.setText("Saisie");
lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
// o campo de entrada (posição, tamanho)
txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
// o botão Exibir (texto, posição, tamanho)
cmdAfficher.setText("Afficher");
cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
// o gerenciador de eventos do botão
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
// adição dos 3 componentes ao contêiner
contentPane.add(lblSaisie, null);
contentPane.add(txtSaisie, null);
contentPane.add(cmdAfficher, null);
}//jbInit
Vale destacar dois pontos:
- esse código poderia ter sido escrito manualmente. Isso significa que é possível dispensar o JBuilder para criar uma interface gráfica.
- a forma como o manipulador de eventos do botão cmdAfficher está definido. O manipulador de eventos do componente cmdAfficher poderia ter sido declarado por cmdAfficher.addActionListener(new manipulador()) onde gestionnaire seria uma classe com um método público actionPerformed encarregado de gerenciar o clique no botão Afficher. Aqui, o JBuilder utiliza como manipulador uma instância de uma classe anônima:
new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
Uma nova instância da interface ActionListener é criada, com seu método actionPerformed definido em seguida. Esse método se limita a chamar um método da classe interface2. Tudo isso não passa de um artifício para definir, na mesma classe da janela, os procedimentos de tratamento dos eventos dos componentes dessa janela. Seria possível proceder de outra forma:
o que faz com que o método actionPerformed seja procurado em this, ou seja, na classe da janela. Esse segundo método parece mais simples, mas o primeiro tem uma vantagem: permite ter manipuladores diferentes para botões diferentes, enquanto o segundo método não permite isso. Neste último caso, de fato, o único método actionPeformed precisa processar os cliques de diferentes botões e, portanto, deve primeiro identificar qual deles está na origem do evento antes de começar a funcionar.
5.2.3.2.3. Os manipuladores de eventos
Encontramos aqui os já estudados:
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
// clique no botão Exibir
void cmdAfficher_actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
}
5.2.3.3. Conclusion
A partir dos dois projetos analisados, podemos concluir que, uma vez criada a interface gráfica com o JBuilder, o trabalho do desenvolvedor consiste em escrever os manipuladores de eventos que ele deseja gerenciar para essa interface gráfica.
5.2.4. Buscando ajuda
Com Java, muitas vezes precisamos de ajuda, principalmente devido ao grande número de classes disponíveis. Apresentamos aqui algumas dicas para encontrar ajuda sobre uma classe. Selecione a opção Ajuda/Tópicos de ajuda no menu.

A tela de ajuda geralmente possui duas janelas:
- a da esquerda, onde se especifica o que se está procurando. Ela possui três abas: Sommaire, Index e Chercher.
- a da direita, que apresenta o resultado da pesquisa
Há uma ajuda sobre como utilizar a ajuda do JBuilder. Selecione, na ajuda do JBuilder, a opção Ajuda/Como usar a ajuda. Lá será explicado como utilizar a ajuda. São indicados, por exemplo, os diferentes componentes do visualizador de ajuda:

Vamos examinar mais de perto as páginas Sommaire e Index.
5.2.4.1. Ajuda: Índice

5.2.4.1.1. Índice: Introdução ao Java
Aqui você encontrará os fundamentos do Java, mas não apenas isso, como mostra a lista de tópicos abordados nesta seção:

5.2.4.1.2. Índice: Tutoriais
Se selecionarmos a opção Tutoriais no índice acima, a janela à direita exibe uma lista dos tutoriais disponíveis:

Os tutoriais básicos são particularmente interessantes para começar a se familiarizar com o JBuilder. Existem muitos outros além dos apresentados acima e, quando se deseja desenvolver um aplicativo, pode ser útil verificar previamente se não há algum tutorial que possa nos ajudar.
5.2.4.1.3. Índice: o JDK
Ao selecionar a opção Java 2 JDK 1.3, tem-se acesso a todas as bibliotecas do JDK. Geralmente, não é aqui que se deve procurar se precisarmos de informações sobre uma classe específica e não soubermos em qual biblioteca ela se encontra. Por outro lado, essa opção é interessante se quisermos ter uma visão geral das bibliotecas do Java.
5.2.4.2. Ajuda: Índice
Selecione a aba Índice na janela à esquerda da Ajuda. Essa opção permite, por exemplo, encontrar ajuda sobre uma classe. Suponhamos, por exemplo, que você queira conhecer os métodos dos campos de entrada swing e JTextField. Digite JTextField no campo de entrada do texto a ser pesquisado:
![]()
A ajuda exibirá as entradas do índice que começam com o texto digitado:

Basta clicar duas vezes na entrada de seu interesse, neste caso, JTextField (classe). A ajuda sobre essa classe será exibida na janela à direita:

Uma descrição completa da classe será exibida.
5.2.5. Alguns componentes do Swing
Apresentamos agora diversas aplicações que utilizam os componentes swing mais comuns, a fim de explorar seus principais métodos e propriedades. Para cada aplicação, apresentamos a interface gráfica e o código relevante, especialmente o dos gerenciadores de eventos.
5.2.5.1. Componentes JLabel e JTextField
Já nos deparamos com esses dois componentes. O JLabel é um componente de texto e o JTextField, um componente de campo de entrada. Seus dois métodos principais são
String getText() | para obter o conteúdo do campo de entrada ou o texto do rótulo |
void setText(String unTexte) | para inserir unTexte no campo ou no rótulo |
Os eventos normalmente utilizados para JTextField são os seguintes:
actionPerformed | indica que o usuário confirmou (tecla Enter) o texto digitado |
caretUpdate | indica que o usuário moveu o cursor de digitação |
inputMethodChanged | indica que o usuário alterou o campo de entrada |
Aqui está um exemplo que utiliza o evento caretUpdate para acompanhar as alterações em um campo de entrada:

n.º | tipo | nome | função |
1 | JTextField | txtSaisie | campo de entrada |
2 | JTextField | txtControle | exibe o texto de 1 em tempo real |
3 | JButton | cmdEffacer | para apagar os campos 1 e 2 |
4 | JButton | cmdQuitter | para sair do aplicativo |
O código relevante deste aplicativo é o seguinte:
import java.awt.*;
....
public class Cadre1 extends JFrame {
JPanel contentPane;
JTextField txtSaisie = new JTextField();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JTextField txtControle = new JTextField();
JButton CmdEffacer = new JButton();
JButton CmdQuitter = new JButton();
/**Construir o quadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
....
txtSaisie.addCaretListener(new javax.swing.event.CaretListener() {
public void caretUpdate(CaretEvent e) {
txtSaisie_caretUpdate(e);
}
});
...
CmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdEffacer_actionPerformed(e);
}
});
...
CmdQuitter.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
CmdQuitter_actionPerformed(e);
}
});
....
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_caretUpdate(CaretEvent e) {
// o cursor de digitação se moveu
txtControle.setText(txtSaisie.getText());
}
void CmdQuitter_actionPerformed(ActionEvent e) {
// saímos do aplicativo
System.exit(0);
}
void CmdEffacer_actionPerformed(ActionEvent e) {
// apagar o conteúdo do campo de entrada
txtSaisie.setText("");
}
}
Aqui está um exemplo de execução:

5.2.5.2. componente JComboBox


Um componente JComboBox é uma lista suspensa acompanhada de um campo de entrada: o usuário pode escolher um item em (2) ou digitar texto em (1). Por padrão, os JComboBox não são editáveis. É necessário chamar explicitamente o método setEditable(true) para que se tornem editáveis. Para conhecer a classe JComboBox, digite JComboBox no índice da ajuda.
O objeto JComboBox pode ser criado de diferentes maneiras:
new JComboBox() | cria um combo vazio |
new JComboBox (Object[] items) | cria um combo contendo uma matriz de objetos |
new JComboBox(Vector items) | o mesmo com um vetor de objetos |
Pode parecer surpreendente que um combo possa conter objetos, já que normalmente ele contém cadeias de caracteres. Visualmente, será esse o caso. Se um JComboBox contiver um objeto obj, ele exibirá a cadeia obj.toString(). Vale lembrar que todo objeto possui um método toString herdado da classe Object, que retorna uma sequência de caracteres “representativa” do objeto.
Os métodos úteis da classe JCombobox são os seguintes:
void addItem(Object unObjet) | adiciona um objeto à lista suspensa |
int getItemCount() | retorna o número de elementos da lista suspensa |
Object getItemAt(int i) | retorna o objeto nº i da lista suspensa |
void insertItemAt(Object unObjet, int i) | insere unObjet na posição i da lista suspensa |
int getSelectedIndex() | retorna o número do elemento selecionado na lista suspensa |
Object getSelectedItem() | retorna o objeto selecionado na lista suspensa |
void setSelectedIndex(int i) | seleciona o elemento i da lista suspensa |
void setSelectedItem(Object unObjet) | seleciona o objeto especificado na lista suspensa |
void removeAllItems() | esvazia a lista suspensa |
void removeItemAt(int i) | remove o elemento nº i da lista suspensa |
void removeItem(Object unObjet) | remove o objeto especificado da lista suspensa |
void setEditable(boolean val) | torna a lista suspensa editável (val=true) ou não (val=false) |
Ao selecionar um item na lista suspensa, ocorre o evento actionPerformed, que pode ser utilizado para ser notificado sobre a alteração na seleção da lista suspensa. No aplicativo a seguir, usamos esse evento para exibir o item que foi selecionado na lista.

Apresentamos apenas o código relevante da janela.
public class Cadre1 extends JFrame {
JPanel contentPane;
JComboBox jComboBox1 = new JComboBox();
JLabel jLabel1 = new JLabel();
/**Construir o quadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// processamento — preenchimento da lista suspensa
String[] infos={"un","deux","trois","quatre"};
for(int i=0;i<infos.length;i++)
jComboBox1.addItem(infos[i]);
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
....
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jComboBox1_actionPerformed(e);
}
});
....
}
void jComboBox1_actionPerformed(ActionEvent e) {
// um novo elemento foi selecionado — exibe-se
JOptionPane.showMessageDialog(this,jComboBox1.getSelectedItem(),
"actionPerformed",JOptionPane.INFORMATION_MESSAGE);
}
}
5.2.5.3. Componente JList
O componente Swing JList é mais complexo do que seu equivalente na biblioteca awt. Há duas diferenças importantes:
- o conteúdo da lista é gerenciado por um objeto diferente da própria lista. Aqui, utilizaremos um objeto DefaultListModel, que funciona como um Vector, mas que, além disso, notifica o objeto JList assim que seu conteúdo é alterado, para que a exibição visual da lista também seja atualizada.
- A lista não possui rolagem por padrão. É necessário colocá-la em um contêiner ScrollPane, que permite essa rolagem.
No código-fonte, a definição de uma lista pode ser feita da seguinte maneira:
// o vetor dos valores da lista
DefaultlistModel valeurs=new DefaultListModel();
// a própria lista à qual se associa o vetor de seus valores
JList jList1 = new JList(valeurs);
// o contêiner rolante no qual a lista é colocada para se obter uma lista rolante
JScrollPane jScrollPane1 = new JScrollPane(jList1);
Para incluir a lista jList1 no contêiner jScrollPane1, o código gerado por JBuilder procede de maneira diferente:
- declaração do contêiner nos atributos da janela
- e, em seguida, no código de jbInit, a lista é associada ao contêiner
Para adicionar valores à lista JList1 acima, basta adicioná-los ao seu vetor de valores valeurs:
e, então, obtém-se a seguinte janela:

Como essa interface é construída?
- escolhe-se um componente JScrollPane na página “Contêineres Swing” dos componentes e o arrasta-se para a janela, ajustando-o ao tamanho desejado
- seleciona-se um componente JList na página “Swing” dos componentes e o arrasta-se para dentro do contêiner JScrollPane, onde ele passa a ocupar todo o espaço.
O código gerado pelo JBuilder deve ser ligeiramente adaptado para obter o código a seguir:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel2 = new JLabel();
/**Construir o quadro*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// processamento
// inclui-se a lista no scrollPane
// inicialização da lista
for(int i=0;i<10;i++)
valeurs.addElement(""+i);
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
....
// a lista jList1 está associada ao contêiner jcrollPane1
jScrollPane1.getViewport().add(jList1, null);
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
....
}
}
Vamos agora conhecer os principais métodos da classe JList, pesquisando por JList no índice da ajuda. O objeto JList pode ser criado de diversas maneiras:

Um método simples é aquele que utilizamos: criar um DefaultListModel com V vazio e, em seguida, associá-lo à lista a ser criada por meio de new JList(V). O conteúdo da lista não é gerenciado pelo objeto JList, mas pelo objeto que contém os valores da lista. Se o conteúdo tiver sido construído com um objeto DefaultListModel baseado na classe Vector, os métodos da classe Vector poderão ser utilizados para adicionar, inserir e excluir elementos da lista. Uma lista pode permitir seleção única ou múltipla. Isso é definido pelo método setSelectionMode:

É possível verificar o modo de seleção atual com o método getSelectionMode:
![]()
O(s) elemento(s) selecionado(s) pode(m) ser obtido(s) por meio dos seguintes métodos:

Sabemos como associar um vetor de valores a uma lista com o construtor JList(DefaultListModel). Por outro lado, podemos obter o objeto DefaultListModel a partir de uma lista JList por meio de:

Já sabemos o suficiente para escrever o seguinte programa:

Os componentes desta janela são os seguintes:
n.º | tipo | nome | função |
1 | JTextField | txtSaisie | campo de entrada |
2 | JList | jList1 | lista contida em um contêiner jScrollPane1 |
3 | JList | jList2 | lista contida em um contêiner jScrollPane2 |
4 | JButton | cmd1To2 | transfere os itens selecionados da lista 1 para a lista 2 |
5 | JButton | cmd2To1 | faz o inverso |
6 | JButton | cmdRaz1 | esvazia a lista 1 |
7 | JButton | cmdRaz2 | esvazia a lista 2 |
O usuário digita um texto no campo (1) e o confirma. Em seguida, ocorre o evento actionPerformed no campo de entrada, que é usado para adicionar o texto digitado à lista 1. Aqui está o código necessário para essa primeira função:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Construir o quadro*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar o componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 é colocado no contêiner jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 é colocado no contêiner jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
// o texto digitado foi validado
// ele é recuperado sem os espaços no início e no final
String texte=txtSaisie.getText().trim();
// se estiver vazio, não o aceitamos
if(texte.equals("")){
// mensagem de erro
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fim
return;
}//se
// se não estiver vazio, adiciona-se aos valores da lista 1
v1.addElement(texte);
// e esvazia-se o campo de entrada
txtSaisie.setText("");
}/// txtSaisie_actionperformed
}//classe
O código para transferir os elementos selecionados de uma lista para a outra é o seguinte:
void cmd1To2_actionPerformed(ActionEvent e) {
// transferência dos itens selecionados da lista 1 para a lista 2
transfert(jList1,jList2);
}//cmd1To2
void cmd2To1_actionPerformed(ActionEvent e) {
// transferência dos elementos selecionados em jList2 para jList1
transfert(jList2,jList1);
}//cmd2TO1
private void transfert(JList L1, JList L2){
// transferência dos elementos selecionados da lista 1 para a lista 2
// recuperamos a matriz de índices dos elementos selecionados em L1
int[] indices=L1.getSelectedIndices();
// há algo a ser feito?
if (indices.length==0) return;
// recuperar os valores de L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// e os de L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// adicionamos a L2 os valores selecionados em L1
v2.addElement(v1.elementAt(indices[i]));
// os elementos de L1 copiados para L2 devem ser excluídos de L1
v1.removeElementAt(indices[i]);
}//para
}//transferência
O código associado aos botões Raz é extremamente simples:
void cmdRaz1_actionPerformed(ActionEvent e) {
// vaziar a lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// vaziar lista 2
v2.removeAllElements();
}///comando Raz2
5.2.5.4. Caixas de seleção JCheckBox, botões de opção JButtonRadio
Propomos escrever o seguinte aplicativo:

Os componentes da janela são os seguintes:
n.º | tipo | nome | função |
1 | JButtonRadio | jButtonRadio1 jButtonRadio2 jButtonRadio3 | 3 botões de opção que fazem parte do grupo buttonGroup1 |
2 | JCheckBox | jCheckBox1 jCheckBox2 jCheckBox3 | 3 caixas de seleção |
3 | JList | jList1 | uma lista em um contêiner jScrollPane1 |
4 | ButtonGroup | buttonGroup1 | componente não visível — serve para agrupar os três botões de opção, de modo que, quando um deles for selecionado, os outros sejam desmarcados. |
Um grupo de botões de opção pode ser criado da seguinte maneira:
- coloca-se cada um dos botões de opção sem se preocupar em agrupá-los
- coloca-se no contêiner um componente Swing ButtonGroup. Esse componente é invisível. Portanto, ele não aparece no editor da janela. No entanto, ele aparece em sua estrutura:

Vemos acima, no ramo Autre, os atributos não visuais da janela. Depois de criar um grupo de botões de opção, é possível associar a ele cada um dos botões de opção. Para isso, seleciona-se as propriedades do botão de opção:

e, na propriedade buttonGroup do botão de opção, insere-se o nome do grupo no qual se deseja colocar o botão de opção, neste caso, buttonGroup1. Repete-se essa operação para os três botões de opção.
O principal método dos botões de opção e caixas de seleção é o método isSelected(), que indica se a caixa ou o botão está marcado. O texto associado ao componente pode ser obtido com getText() e definido com setText(String unTexte). A caixa de seleção/botão de opção pode ser marcada com o método setSelected(boolean value).
Ao clicar em um botão de opção ou em uma caixa de seleção, é acionado o evento actionPerformed. No código a seguir, utilizamos esse evento para acompanhar as alterações nos valores dos botões de opção e das caixas de seleção:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JRadioButton jRadioButton1 = new JRadioButton();
JRadioButton jRadioButton2 = new JRadioButton();
JRadioButton jRadioButton3 = new JRadioButton();
JCheckBox jCheckBox1 = new JCheckBox();
JCheckBox jCheckBox2 = new JCheckBox();
JCheckBox jCheckBox3 = new JCheckBox();
ButtonGroup buttonGroup1 = new ButtonGroup();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList jList1 = new JList(valeurs);
/**Construir o quadro*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
jRadioButton1.setSelected(true);
jRadioButton1.setText("un");
jRadioButton1.setBounds(new Rectangle(57, 31, 49, 23));
jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setBounds(new Rectangle(113, 30, 49, 23));
jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton2.setText("deux");
jRadioButton3.setBounds(new Rectangle(168, 30, 49, 23));
jRadioButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheRadioButtons(e);
}
});
jRadioButton3.setText("trois");
// os botões de opção estão agrupados
buttonGroup1.add(jRadioButton1);
buttonGroup1.add(jRadioButton2);
buttonGroup1.add(jRadioButton3);
// caixas de seleção
jCheckBox1.setText("A");
jCheckBox1.setBounds(new Rectangle(58, 69, 32, 17));
jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setBounds(new Rectangle(112, 69, 40, 17));
jCheckBox2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
jCheckBox2.setText("B");
jCheckBox3.setText("C");
jCheckBox3.setBounds(new Rectangle(170, 69, 37, 17));
jCheckBox3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
afficheCases(e);
}
});
....
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
...
}
private void afficheRadioButtons(ActionEvent e){
// exibe os valores dos 3 botões de opção
valeurs.addElement("boutons radio=("+jRadioButton1.isSelected()+","+
jRadioButton2.isSelected()+","+jRadioButton3.isSelected()+")");
}//afficheRadioButtons
void afficheCases(ActionEvent e) {
// exibe os valores das caixas de seleção
valeurs.addElement("cases à cocher=["+jCheckBox1.isSelected()+","+
jCheckBox2.isSelected()+","+jCheckBox3.isSelected()+")");
}//afficheCases
}//classifica
Aqui está um exemplo de execução:

5.2.5.5. componente JScrollBar
Vamos criar o seguinte aplicativo:

n.º | tipo | nome | função |
1 | JScrollBar | jScrollBar1 | um variador horizontal |
2 | JScrollBar | jScrollBar2 | um variador vertical |
3 | JTextField | txtvaleurHS | exibe o valor do variador horizontal 1 — também permite definir esse valor |
4 | JTextField | txtvaleurVS | exibe o valor do regulador vertical 2 — também permite definir esse valor |
- Um regulador JScrollBar permite que o usuário escolha um valor dentro de um intervalo de valores inteiros, representado pela “faixa” do regulador sobre a qual se move um cursor.
- Para um variador horizontal, a extremidade esquerda representa o valor mínimo do intervalo, a extremidade direita o valor máximo e o cursor o valor atual selecionado. Para um variador vertical, o mínimo é representado pela extremidade superior e o máximo pela extremidade inferior. O par (mín., máx.) tem o valor padrão (0,100).
- Um clique nas extremidades do variador altera o valor em um incremento (positivo ou negativo), dependendo da extremidade clicada, denominada unitIncrement, cujo valor padrão é 1.
- Um clique em cada lado do cursor altera o valor em um incremento (positivo ou negativo), dependendo da extremidade clicada, denominada blockIncrement, cujo valor padrão é 10.
- Esses cinco valores (mín., máx., valor, unitIncrement, blockIncrement) podem ser obtidos por meio dos métodos getMinimum(), getMaximum(), getValue(), getUnitIncrement(), getBlockIncrement(), todos os quais retornam um inteiro e podem ser definidos pelos métodos setMinimum(int min), setMaximum(int max), setValue(int val), setUnitIncrement(int uInc), setBlockIncrement(int bInc)
Há alguns pontos que devem ser considerados ao utilizar os componentes JScrollBar. Em primeiro lugar, ele pode ser encontrado na barra de componentes do Swing:

Ao arrastá-lo para o contêiner, ele fica, por padrão, na orientação vertical. É possível torná-lo horizontal com a propriedade orientation abaixo:

Na folha de propriedades acima, vemos que temos acesso às propriedades minimum, maximum, value, unitIncrement, blockIncrement do JScrollbar. Portanto, é possível defini-las na fase de projeto. Ao inserir uma barra de rolagem no contêiner, sua “faixa de variação” não aparece:

É possível resolver esse problema atribuindo uma borda ao componente. Isso é feito por meio da propriedade border, que pode assumir diferentes valores:

Veja, por exemplo, o resultado de RaisedBevel:
![]()
Ao clicar na extremidade superior de um controle deslizante vertical, seu valor diminui. Isso pode surpreender o usuário comum, que normalmente espera ver o valor “aumentar”. Resolvemos esse problema atribuindo um valor negativo a unitIncrement e blockIncrement.
Como acompanhar as variações de um controle deslizante? Quando o valor dele muda, ocorre o evento adjustmentValueChanged. Basta associar um procedimento a esse evento para ser informado sobre cada variação no valor da barra de rolagem.

O código útil do nosso aplicativo é o seguinte:
....
public class cadreAppli extends JFrame {
JPanel contentPane;
JScrollBar jScrollBar1 = new JScrollBar();
Border border1;
JTextField txtValeurHS = new JTextField();
JScrollBar jScrollBar2 = new JScrollBar();
JTextField txtValeurVS = new JTextField();
TitledBorder titledBorder1;
/**Construir o quadro*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
...
// uma borda para as barras de rolagem
border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.white,Color.white,new Color(134, 134, 134),new Color(93, 93, 93));
// sem título na borda
titledBorder1 = new TitledBorder("");
jScrollBar1.setOrientation(JScrollBar.HORIZONTAL);
jScrollBar1.setBorder(BorderFactory.createRaisedBevelBorder());
jScrollBar1.setAutoscrolls(true);
jScrollBar1.setBounds(new Rectangle(37, 17, 218, 20));
jScrollBar1.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar1_adjustmentValueChanged(e);
}
});
txtValeurHS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurHS_actionPerformed(e);
}
});
jScrollBar2.setBounds(new Rectangle(39, 51, 30, 27));
jScrollBar2.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
jScrollBar2_adjustmentValueChanged(e);
}
});
jScrollBar2.setAutoscrolls(true);
jScrollBar2.setUnitIncrement(-1);
jScrollBar2.setBorder(BorderFactory.createRaisedBevelBorder());
txtValeurVS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtValeurVS_actionPerformed(e);
}
});
......
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
...
}
void jScrollBar1_adjustmentValueChanged(AdjustmentEvent e) {
// o valor da barra de rolagem 1 mudou
txtValeurHS.setText(""+jScrollBar1.getValue());
}
void jScrollBar2_adjustmentValueChanged(AdjustmentEvent e) {
// o valor da barra de rolagem 2 mudou
txtValeurVS.setText(""+jScrollBar2.getValue());
}
void txtValeurHS_actionPerformed(ActionEvent e) {
// definimos o valor da barra de rolagem horizontal
setValeur(jScrollBar1,txtValeurHS);
}
void txtValeurVS_actionPerformed(ActionEvent e) {
// fixamos o valor da barra de rolagem vertical
setValeur(jScrollBar2,txtValeurVS);
}
private void setValeur(JScrollBar jS, JTextField jT){
// define o valor da barra de rolagem jS com o texto do campo jT
int valeur=0;
try{
valeur=Integer.parseInt(jT.getText());
jS.setValue(valeur);
}
catch (Exception e){
// exibe o erro
afficher(""+e);
}//try-catch
}//setValeur
void afficher(String message){
// exibe uma mensagem em uma caixa de diálogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//exibir
}
Aqui está um exemplo de execução:

5.2.5.6. componente JTextArea
O componente JTextArea é um componente no qual é possível inserir várias linhas de texto, ao contrário do componente JTextField, no qual só é possível inserir uma linha. Se esse componente for colocado em um contêiner rolante (JScrollPane), teremos um campo de entrada de texto rolante. Esse tipo de componente pode ser encontrado, por exemplo, em um aplicativo de e-mail, onde o texto da mensagem a ser enviada seria digitado em um componente JTextArea. Os métodos usuais são String getText() para obter o conteúdo da área de texto, setText(String unTexte) para inserir unTexte na área de texto e append(String unTexte) para adicionar unTexte ao texto já presente na área de texto. Consideremos o seguinte aplicativo:

n.º | tipo | nome | função |
1 | JTextArea | txtTexte | um campo de texto multilinha |
2 | JButton | cmdAfficher | exibe o conteúdo de 1 em uma caixa de diálogo |
3 | JButton | cmdEffacer | apaga o conteúdo de 1 |
4 | JTextField | txtAjout | texto adicionado ao texto de 1 quando validado pela tecla Enter. |
5 | JScrollPane | jScrollPane1 | contêiner rolante no qual foi inserida a área de texto 1 para que haja uma área de texto rolante. |
O código necessário é o seguinte:
.....
public class cadreAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JButton cmdAfficher = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JLabel jLabel2 = new JLabel();
JTextField txtAjout = new JTextField();
JButton cmdEffacer = new JButton();
/**Construir o quadro*/
public cadreAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdAfficher_actionPerformed(e);
}
});
txtAjout.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtAjout_actionPerformed(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
.......
jScrollPane1.getViewport().add(txtTexte, null);
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
........
}
void cmdAfficher_actionPerformed(ActionEvent e) {
// exibe o conteúdo de TextArea
afficher(txtTexte.getText());
}
void afficher(String message){
// exibe uma mensagem em uma caixa de diálogo
JOptionPane.showMessageDialog(this,message,"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// exibir
void cmdEffacer_actionPerformed(ActionEvent e) {
txtTexte.setText("");
}//cmdEffacer_actionPerformed
void txtAjout_actionPerformed(ActionEvent e) {
// adicionar texto
txtTexte.append(txtAjout.getText());
// limpar e adicionar
txtAjout.setText("");
}//
}
5.2.6. Eventos do mouse
Ao desenhar em um contêiner, é importante saber a posição do mouse para, por exemplo, exibir um ponto ao clicar. Os movimentos do mouse geram eventos no contêiner em que ele se move. Aqui estão, por exemplo, os eventos oferecidos pelo JBuilder para um contêiner JPanel:

mouseClicked | clique do mouse |
mouseDragged | o mouse se move, botão esquerdo pressionado |
mouseEntered | o mouse acaba de entrar na área do contêiner |
mouseExited | o mouse acabou de sair da área do contêiner |
mouseMoved | o mouse está se movendo |
mousePressed | Pressão no botão esquerdo do mouse |
mouseReleased | Solte o botão esquerdo do mouse |
Aqui está um programa que ajuda a entender melhor em que momentos ocorrem os diferentes eventos do mouse:

n.º | tipo | nome | função |
1 | JTextField | txtPosition | para exibir a posição do mouse no contêiner (se necessário, MouseMoved) |
2 | JList | lstAffichage | para exibir os eventos do mouse diferentes de MouseMoved |
3 | JButton | cmdEffacer | para apagar o conteúdo de 2 |
Ao executar este programa, eis o que se obtém ao clicar:

Os eventos são empilhados a partir do topo na lista. Portanto, a captura de tela acima indica que um clique gera três eventos, na seguinte ordem:
- MousePressed ao pressionar o botão
- MouseReleased ao soltá-lo
- MouseClicked, que indica que a sucessão dos dois eventos anteriores é considerada um clique. Poderia ser um clique duplo. Mas, acima, a informação clickCount=1 indica que se trata de um clique simples.
Agora, se você clicar no botão, mover o mouse e soltar o botão:

Vemos aqui os três eventos:
- MousePressed ao pressionar o botão inicialmente
- MouseDragged ao mover o mouse com o botão pressionado
- MouseReleased ao soltar o botão
Nos dois exemplos acima, percebe-se que um evento do mouse traz consigo diversas informações, incluindo as coordenadas (x, y) do mouse, por exemplo (408,65) na primeira linha acima.
Se continuarmos assim, descobrimos que o evento MouseExited é acionado assim que o mouse sai do contêiner ou passa por cima de um de seus componentes. Neste último caso, o contêiner recebe o evento MouseExited e o componente, o evento MouseEntered. O inverso ocorrerá quando o mouse sair do componente para voltar ao contêiner.
O que acontece ao clicar duas vezes?

Temos exatamente os mesmos eventos que em um clique simples. A única diferença é que o evento traz consigo a informação clickCount=2 (veja acima), indicando que, na verdade, houve um clique duplo.
O código relevante desta aplicação é o seguinte:
public class Cadre1 extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtPosition = new JTextField();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel valeurs=new DefaultListModel();
JList lstAffichage = new JList(valeurs);
JButton cmdEffacer = new JButton();
/**Construir o quadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
contentPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
contentPane_mouseMoved(e);
}
public void mouseDragged(MouseEvent e) {
contentPane_mouseDragged(e);
}
});
contentPane.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(MouseEvent e) {
contentPane_mouseEntered(e);
}
public void mouseExited(MouseEvent e) {
contentPane_mouseExited(e);
}
public void mousePressed(MouseEvent e) {
contentPane_mousePressed(e);
}
public void mouseClicked(MouseEvent e) {
contentPane_mouseClicked(e);
}
public void mouseReleased(MouseEvent e) {
contentPane_mouseReleased(e);
}
});
cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
cmdEffacer_actionPerformed(e);
}
});
jScrollPane1.getViewport().add(lstAffichage, null);
...............
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
.........
}
void contentPane_mouseMoved(MouseEvent e) {
txtPosition.setText("("+e.getX()+","+e.getY()+")");
}
void contentPane_mouseDragged(MouseEvent e) {
afficher(e);
}
void contentPane_mouseEntered(MouseEvent e) {
afficher(e);
}
void afficher(MouseEvent e){
// exibe o evento na lista lstAffichage
valeurs.insertElementAt(e,0);
}
void contentPane_mouseExited(MouseEvent e) {
afficher(e);
}
void contentPane_mousePressed(MouseEvent e) {
afficher(e);
}
void contentPane_mouseClicked(MouseEvent e) {
afficher(e);
}
void contentPane_mouseReleased(MouseEvent e) {
afficher(e);
}
void cmdEffacer_actionPerformed(ActionEvent e) {
// limpa a lista
valeurs.removeAllElements();
}
}
5.2.7. Criar uma janela com menu
Vamos ver agora como criar uma janela com menu usando o JBuilder. Vamos criar a seguinte janela:


Crie um novo projeto com uma janela vazia inicialmente. Na lista de componentes “Contêineres Swing”, selecione o componente JMenuBar (ver Fig. 1 abaixo) e arraste-o para a janela que está sendo projetada.

Nada aparece na janela de design, mas o componente JMenuBar aparece no painel de estrutura da sua janela:

Clique duas vezes no elemento jMenuBar1 acima para acessar o menu no modo de projeto:

1 | Inserir um item de menu |
2 | inserir um separador |
3 | inserir um menu aninhado |
4 | excluir um item do menu |
5 | desativar um item de menu |
6 | item de menu com caixa de seleção |
7 | inverter o botão de opção |
Para criar seu primeiro item de menu, digite “Opções A” no campo A acima e, em seguida, abaixo, na seguinte ordem: A1, A2, separador, A3, A4.

Em seguida, ao lado:

Use a ferramenta 3 para indicar que B3 é um submenu aninhado.
À medida que o menu é projetado, a estrutura lógica da nossa janela evolui:

Se executarmos nosso aplicativo agora, veremos uma janela vazia, sem menu. Precisamos associar o menu criado à nossa janela. Para isso, na estrutura da janela, selecione o objeto this:

Você terá então acesso às propriedades de this:

Uma delas é JMenuBar, que serve para definir o menu que será associado à janela. Clique na célula à direita de JMenuBar. Todos os menus criados serão exibidos. Neste caso, teremos apenas jMenuBar1. Selecione-o.
Inicie a execução do aplicativo (F9):

Agora, temos um menu, mas as opções, por enquanto, não fazem nada. As opções do menu são tratadas como componentes: elas têm propriedades e eventos. Na estrutura do menu, selecione a opção jMenuItem1:

Você terá então acesso às propriedades e eventos dessa opção:

Selecione a página de eventos e clique na célula à direita do evento actionPerformed: esse é o evento que ocorre quando se clica em um item do menu. Um procedimento de processamento é proposto por padrão. Clique duas vezes nele para acessar seu código:

Escreveremos o seguinte código simples:
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// exibe uma mensagem em uma caixa de diálogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//exibir
Execute o aplicativo e selecione a opção A1 para obter a seguinte mensagem:

O código útil deste aplicativo é o seguinte:
.....
public class Cadre1 extends JFrame {
JPanel contentPane;
BorderLayout borderLayout1 = new BorderLayout();
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem jMenuItem1 = new JMenuItem();
JMenuItem jMenuItem2 = new JMenuItem();
JMenuItem jMenuItem3 = new JMenuItem();
JMenuItem jMenuItem4 = new JMenuItem();
JMenu jMenu2 = new JMenu();
JMenuItem jMenuItem5 = new JMenuItem();
JMenuItem jMenuItem6 = new JMenuItem();
JMenu jMenu3 = new JMenu();
JMenuItem jMenuItem7 = new JMenuItem();
JMenuItem jMenuItem8 = new JMenuItem();
JMenuItem jMenuItem9 = new JMenuItem();
/**Construir o quadro*/
public Cadre1() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
/**Inicializar o componente*/
private void jbInit() throws Exception {
// a janela está associada a um menu
this.setJMenuBar(jMenuBar1);
jMenu1.setText("Options A");
jMenuItem1.setText("A1");
jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuItem1_actionPerformed(e);
}
});
jMenuItem2.setText("A2");
jMenuItem3.setText("A3");
jMenuItem4.setText("A4");
jMenu2.setText("Options B");
jMenuItem5.setText("B1");
jMenuItem6.setText("B2");
jMenu3.setText("B3");
jMenuItem7.setText("B31");
jMenuItem8.setText("B32");
jMenuItem9.setText("B4");
jMenuBar1.add(jMenu1);
jMenuBar1.add(jMenu2);
jMenu1.add(jMenuItem1);
jMenu1.add(jMenuItem2);
jMenu1.addSeparator();
jMenu1.add(jMenuItem3);
jMenu1.add(jMenuItem4);
jMenu2.add(jMenuItem5);
jMenu2.add(jMenuItem6);
jMenu2.add(jMenu3);
jMenu2.add(jMenuItem9);
jMenu3.add(jMenuItem7);
jMenu3.add(jMenuItem8);
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
....
}
void jMenuItem1_actionPerformed(ActionEvent e) {
afficher("L'option A1 a été sélectionnée");
}
void afficher(String message){
// exibe uma mensagem em uma caixa de diálogo
JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
}//exibir
}
5.3. Caixas de diálogo
5.3.1. Caixas de mensagem
Já utilizamos a classe JOptionPane para exibir mensagens. Assim, o código a seguir:
import javax.swing.*;
public class dialog1 {
public static void main(String arg[]){
JOptionPane.showMessageDialog(null,"Un message","Titre de la boîte",JOptionPane.INFORMATION_MESSAGE);
}
}
gera a exibição da seguinte caixa:

Quando essa janela é fechada, ela desaparece, mas o thread de execução no qual ela estava sendo executada não é interrompido. Esse fenômeno normalmente não ocorre. As caixas de diálogo são utilizadas dentro de um aplicativo que, em algum momento, utiliza uma instrução System.exit(n) para interromper todos os threads. Lembraremos disso nos exemplos a seguir, todos construídos com base no mesmo modelo. No DOS, o aplicativo pode ser interrompido com Ctrl-C. Com JBuilder, utilizaremos a opção Executar/Reiniciar o programa (Ctrl-F2). Além disso, o primeiro argumento de showMessageDialog é, neste caso, null. Em geral, esse não é o caso. Normalmente, é this, em que this designa a janela principal do aplicativo.
5.3.2. Aparência e comportamento
A aparência da caixa acima pode ser diferente. É possível definir essa aparência por meio da classe javax.swing.UIManager. Quando comentamos o código gerado por JBuilder para nossa primeira janela, encontramos uma instrução na qual não nos detivemos:
O método setLookAndFeel da classe UIManager (UI = Interface do Usuário) permite definir a aparência das interfaces gráficas. A classe UIManager possui um método que permite identificar as “aparências” possíveis para as interfaces:
static UIManager.LookAndFeelInfo[] | getInstalledLookAndFeels() |
O método retorna uma matriz de elementos do tipo LookAndFeelInfo. Essa classe possui um método:
String | getClassName() |
que retorna o nome da classe que “implementa” um determinado tema. Vamos testar o seguinte programa:
import javax.swing.*;
public class LookAndFeels {
// exibe os “look and feels” disponíveis
public static void main(String[] args) {
// lista os “look and feels” instalados
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// exibição
for(int i=0;i<lf.length;i++){
System.out.println(lf[i].getClassName());
}//para
}//principal
}//classificar
Isso gera os seguintes resultados:
javax.swing.plaf.metal.MetalLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Portanto, parece haver três “aparências” diferentes. Vamos retomar nosso programa de exibição de mensagens, testando as diferentes aparências possíveis:
import javax.swing.*;
public class LookAndFeel2 {
// exibe os “look and feels” disponíveis
public static void main(String[] args) {
// lista dos look and feels instalados
UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
// exibição
for(int i=0;i<lf.length;i++){
// gerenciador de aparência
try{
UIManager.setLookAndFeel(lf[i].getClassName());
}catch(Exception ex){
System.err.println(ex.getMessage());
}//captura
// mensagem
JOptionPane.showMessageDialog(null,"Un message",lf[i].getClassName(),JOptionPane.INFORMATION_MESSAGE);
}//for
}//main
}//classe
A execução gera as seguintes exibições:
![]() | ![]() | ![]() |
correspondentes, da direita para a esquerda, aos “looks” Metal, Motivo e Windows.
5.3.3. Caixas de confirmação
A classe JOptionPane possui um método showConfirmDialog para exibir caixas de confirmação com os botões Oui, Non e Annuler. Existem vários métodos showConfirmDialog sobrecarregados. Analisaremos um deles:
static int | showConfirmDialog(Component parentComponent, Object message, String title, int optionType) |
parentComponent | o componente pai da caixa de diálogo. Geralmente, a janela ou o valor nulo |
message | a mensagem a ser exibida |
title | o título da caixa de diálogo |
optionType | JOptionPane.YES_NO_OPTION: botões “sim”, “não” JOptionPane.YES_NO_CANCEL_OPTION: botões “sim”, “não”, “cancelar” |
O resultado retornado pelo método é:
JOptionPane.YES_OPTION | o usuário clicou em “sim” |
JOptionPane.NO_OPTION | o usuário clicou em “não” |
JOptionPane.CANCEL_OPTION | o usuário clicou em “Cancelar” |
JOptionPane.CLOSED_OPTION | o usuário fechou a caixa |
Veja um exemplo:
import javax.swing.*;
public class confirm1 {
public static void main(String[] args) {
// exibe caixas de confirmação
int réponse;
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_OPTION));
affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_CANCEL_OPTION));
}//principal
private static void affiche(int réponse){
// indica que tipo de resposta foi recebida
switch(réponse){
case JOptionPane.YES_OPTION :
System.out.println("Oui");
break;
case JOptionPane.NO_OPTION :
System.out.println("Non");
break;
case JOptionPane.CANCEL_OPTION :
System.out.println("Annuler");
break;
case JOptionPane.CLOSED_OPTION :
System.out.println("Fermeture");
break;
}//switch
}//exibe
}//classificar
![]() | ![]() |
No console, são exibidas as mensagens Non e Annuler.
5.3.4. Campo de entrada
A classe JOptionPane também oferece a possibilidade de realizar uma entrada com o método showInputDialog. Mais uma vez, existem vários métodos sobrecarregados. Apresentamos um deles:
static String | showInputDialog(Component parentComponent, Object message, String title, int messageType) |
Os argumentos são os mesmos que já vimos várias vezes. O método retorna a sequência de caracteres digitada pelo usuário. Veja um exemplo:
import javax.swing.*;
public class input1 {
public static void main(String[] args) {
// entrada
System.out.println("Chaîne saisie ["+
JOptionPane.showInputDialog(null,"Quel est votre nom","Saisie du nom",JOptionPane.QUESTION_MESSAGE )
+ "]");
}//mão
}//classe
Exibição do campo de entrada:

Exibição do console:
5.4. Caixas de seleção
Vamos agora nos concentrar em algumas caixas de seleção predefinidas no Java 2:
JFileChooser | caixa de seleção que permite selecionar um arquivo na árvore de arquivos |
JColorChooser | caixa de seleção que permite escolher uma cor |
5.4.1. Caixa de seleção JFileChooser
Vamos criar o seguinte aplicativo:

Os controles são os seguintes:
Nº | tipo | nome | função |
0 | JScrollPane | jScrollPane1 | Contêiner rolante para a caixa de texto 1 |
1 | O próprio JTextArea no JScrollPane | txtTexte | texto digitado pelo usuário ou carregado a partir de um arquivo |
2 | JButton | btnSauvegarder | permite salvar o texto de 1 em um arquivo de texto |
3 | JButton | btnCharger | permite carregar o conteúdo de um arquivo de texto em 1 |
4 | JButton | btnEffacer | apaga o conteúdo de 1 |
É utilizado um controle não visual: jFileChooser1. Este é obtido da paleta de contêineres Swing do JBuilder:

Colocamos o componente na janela de design, mas fora do formulário. Ele aparece na lista de componentes:

Apresentamos agora o código relevante do programa para se ter uma visão geral:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
public class dialogues extends JFrame {
// os componentes do quadro
JPanel contentPane;
JButton btnSauvegarder = new JButton();
JButton btnCharger = new JButton();
JButton btnEffacer = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
JTextArea txtTexte = new JTextArea();
JFileChooser jFileChooser1 = new JFileChooser();
// filtros de arquivos
javax.swing.filechooser.FileFilter filtreTxt = null;
//Construir o quadro
public dialogues() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
// outras inicializações
moreInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
// moreInit
private void moreInit(){
// inicializações na construção da janela
// filtro *.txt
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// aceita-se f?
return f.getName().toLowerCase().endsWith(".txt");
}//aceitar
public String getDescription(){
// descrição do filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// adicionamos o filtro
jFileChooser1.addChoosableFileFilter(filtreTxt);
// também queremos o filtro para todos os arquivos
jFileChooser1.setAcceptAllFileFilterUsed(true);
// definimos o diretório inicial da caixa FileChooser como o diretório atual
jFileChooser1.setCurrentDirectory(new File("."));
}
//Inicializar o componente
private void jbInit() throws Exception {
.......................
}
//Substituído, assim podemos sair quando a janela for fechada
protected void processWindowEvent(WindowEvent e) {
......................
}
}
void btnCharger_actionPerformed(ActionEvent e) {
// seleção de um arquivo por meio de um objeto JFileChooser
// definimos o filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// exibe-se a caixa de seleção
int returnVal = jFileChooser1.showOpenDialog(this);
// o usuário selecionou alguma opção?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// coloca-se o arquivo no campo de texto
lireFichier(jFileChooser1.getSelectedFile());
}//if
}//btnCharger_actionPerformed
// lireFichier
private void lireFichier(File fichier){
// exibe o conteúdo do arquivo de texto no campo de texto
// limpa o campo de texto
txtTexte.setText("");
// algumas informações
BufferedReader IN=null;
String ligne=null;
try{
// abre o arquivo para leitura
IN=new BufferedReader(new FileReader(fichier));
// lê-se o arquivo linha por linha
while((ligne=IN.readLine())!=null){
txtTexte.append(ligne+"\n");
}//while
// fechamento do arquivo
IN.close();
}catch(Exception ex){
// ocorreu um erro
txtTexte.setText(""+ex);
}//catch
}
// apagar
void btnEffacer_actionPerformed(ActionEvent e) {
// apagando a caixa de texto
txtTexte.setText("");
}
// salvar
void btnSauvegarder_actionPerformed(ActionEvent e) {
// salva o conteúdo da caixa de texto em um arquivo
// define o filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// exibe a caixa de seleção para salvar
int returnVal = jFileChooser1.showSaveDialog(this);
// o usuário selecionou alguma opção?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// grava-se o conteúdo da caixa de texto em um arquivo
écrireFichier(jFileChooser1.getSelectedFile());
}//if
}
// lireFichier
private void écrireFichier(File fichier){
// grava o conteúdo da caixa de texto em um arquivo
// algumas informações
PrintWriter PRN=null;
try{
// abre o arquivo para gravação
PRN=new PrintWriter(new FileWriter(fichier));
// grava o conteúdo da caixa de texto
PRN.print(txtTexte.getText());
// fechamento do arquivo
PRN.close();
}catch(Exception ex){
// ocorreu um erro
txtTexte.setText(""+ex);
}//captura
}
Não comentaremos o código dos métodos btnEffacer_Click, lireFichier e écrireFichier, pois não trazem nada que já não tenha sido visto. Vamos nos concentrar na classe JFileChooser e em sua utilização. Essa classe é complexa, do tipo “muito complicada”. Aqui, utilizamos apenas os seguintes métodos:
addChoosableFilter(FileFilter) | define os tipos de arquivos disponíveis para seleção |
setAcceptAllFileFilterUsed(boolean) | indica se o tipo “Todos os arquivos” deve ou não ser oferecido para seleção |
File getSelectedFile() | o arquivo (File) escolhido pelo usuário |
int showSaveDialog() | método que exibe a caixa de seleção para salvar. Retorna um resultado do tipo int. O valor jFileChooser.APPROVE_OPTION indica que o usuário fez uma escolha válida. Caso contrário, ele cancelou a escolha ou ocorreu um erro. |
setCurrentDirectory | para definir o diretório inicial a partir do qual o usuário começará a explorar o sistema de arquivos |
setFileFilter(FileFilter) | para definir o filtro ativo |
O método showSaveDialog exibe uma caixa de seleção semelhante à seguinte:

1 | lista suspensa criada com o método addChoosableFilter. Ela contém os chamados filtros de seleção, representados pela classe FileFilter. Cabe ao desenvolvedor definir esses filtros e adicioná-los à lista 1. |
2 | pasta atual, definida pelo método setCurrentDirectory, caso esse método tenha sido utilizado; caso contrário, a pasta atual será a pasta “Meus Documentos” no Windows ou o diretório home no Unix. |
3 | nome do arquivo selecionado ou digitado diretamente pelo usuário. Estará disponível com o método getSelectedFile() |
4 | botões “Salvar”/“Cancelar”. Se o botão Enregistrer for utilizado, o método showSaveDialog retorna o resultado jFileChooser.APPROVE_OPTION |
Como os filtros de arquivos da lista suspensa 1 são criados? Os filtros são adicionados à lista 1 por meio do método:
addChoosableFilter(FileFilter) | define os tipos de arquivos disponíveis para seleção |
da classe JFileChooser. Resta-nos conhecer a classe FileFilter. Na verdade, trata-se da classe javax.swing.filechooser.FileFilter, que é uma classe abstrata, c.a.d — uma classe que não pode ser instanciada, mas apenas derivada. Ela é definida da seguinte forma:
FileFilter() | construtor |
boolean accept(File) | indica se o arquivo f pertence ao filtro ou não |
String getDescription() | cadeia de caracteres com a descrição do filtro |
Vejamos um exemplo. Queremos que a lista suspensa 1 ofereça um filtro para selecionar os arquivos *.txt com a descrição “Arquivos de texto (*.txt)”.
- Precisamos criar uma classe derivada da classe FileFilter
- usar o método boolean accept(File f) para retornar o valor true se o nome do arquivo f terminar em .txt
- usar o método String getDescription() para retornar a descrição “Arquivos de texto (*.txt)”
Esse filtro poderia ser definido em nosso aplicativo da seguinte maneira:
javax.swing.filechooser.FileFilter filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// aceita-se f?
return f.getName().toLowerCase().endsWith(".txt");
}//aceitar
public String getDescription(){
// descrição do filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
Esse filtro seria adicionado à lista de filtros do objeto jFileChooser1 por meio da instrução:
Tudo isso e algumas outras inicializações são realizadas no método moreInit, executado durante a construção da janela (ver programa completo acima). O código do botão Sauvegarder é o seguinte:
void btnSauvegarder_actionPerformed(ActionEvent e) {
// salva o conteúdo da caixa de texto em um arquivo
// define-se o filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// exibe a caixa de seleção para salvar
int returnVal = jFileChooser1.showSaveDialog(this);
// o usuário selecionou alguma opção?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// grava-se o conteúdo da caixa de texto em um arquivo
écrireFichier(jFileChooser1.getSelectedFile());
}//if
}
A sequência de operações é a seguinte:
- define-se o filtro ativo como *.txt para permitir que o usuário pesquise preferencialmente esse tipo de arquivo. O filtro “Todos os arquivos” também está presente. Ele foi adicionado no procedimento moreInit. Portanto, temos dois filtros.
- A caixa de seleção para salvamento é exibida. Aqui perdemos o controle, pois o usuário utiliza a caixa de seleção para indicar um arquivo do sistema de arquivos.
- Quando ele sai da caixa de seleção, verifica-se o valor de retorno para determinar se a caixa de texto deve ou não ser salva. Se sim, ela deve ser salva no arquivo obtido pelo método getSelectedFile.
O código relacionado ao botão “Carregar” é muito semelhante ao código do botão “Salvar”.
void btnCharger_actionPerformed(ActionEvent e) {
// escolha de um arquivo por meio de um objeto JFileChooser
// define-se o filtro inicial
jFileChooser1.setFileFilter(filtreTxt);
// exibe-se a caixa de seleção
int returnVal = jFileChooser1.showOpenDialog(this);
// o usuário selecionou alguma opção?
if(returnVal == JFileChooser.APPROVE_OPTION) {
// coloca-se o arquivo no campo de texto
lireFichier(jFileChooser1.getSelectedFile());
}//if
}//btnCharger_actionPerformed
Existem duas diferenças:
- para exibir a caixa de seleção de arquivos, utiliza-se o método showOpenDialog em vez do método showSaveDialog. A caixa de seleção exibida é semelhante à exibida pelo método showSaveDialog.
- Se o usuário selecionou corretamente um arquivo, chama-se o método lireFichier em vez do método écrireFichier.
5.4.1.1. Caixas de seleção JColorChooser e JFontChooser
Continuamos o exemplo anterior adicionando dois novos botões:

N.º | tipo | nome | função |
6 | JButton | btnCouleur | para definir a cor dos caracteres do TextBox |
7 | JButton | btnPolice | para definir a fonte do TextBox |
O componente JColorChooser, que permite exibir uma caixa de seleção de cores, pode ser encontrado na lista de componentes Swing do JBuilder:

Colocamos esse componente na janela de design, mas fora do formulário. Ele não fica visível no formulário, mas está presente na lista de componentes da janela:

A classe JColorChooser é muito simples. Exibimos a caixa de seleção de cores com o método int showDialog:
static Color | showDialog(Component component, String title, Color initialColor) |
Component component | o componente pai da caixa de seleção, geralmente uma janela JFrame |
String title | o título na barra de título da caixa de seleção |
Cor intialColor | cor inicialmente selecionada na caixa de seleção |
Se o usuário escolher uma cor, o método retorna uma cor; caso contrário, retorna o valor null. O código associado ao botão Couleur é o seguinte:
void btnCouleur_actionPerformed(ActionEvent e) {
// escolha de uma cor de texto usando o componente JColorChooser
Color couleur;
if((couleur=jColorChooser1.showDialog(this,"Choix d'une couleur",Color.BLACK))!=null){
// definimos a cor dos caracteres da caixa de texto
txtTexte.setForeground(couleur);
}//if
}
A classe Color está definida em java.awt.Color. Nela estão definidas várias constantes, entre elas Color.BLACK para a cor preta. A caixa de seleção exibida é a seguinte

Curiosamente, a biblioteca Swing não oferece uma classe para selecionar um tipo de fonte. Felizmente, existem os recursos Java disponíveis na internet. Ao pesquisar a palavra-chave “JFontChooser” — que parece ser um nome possível para tal classe —, encontramos várias opções. O exemplo a seguir nos dará a oportunidade de configurar o JBuilder para que ele utilize pacotes não previstos em sua configuração inicial.
O pacote recuperado se chama swingextras.jar e foi colocado na pasta <jdk>\jre\lib\perso, onde <jdk> indica o diretório de instalação do JDK utilizado pelo JBuilder. Ele poderia ter sido colocado em qualquer outro lugar.
![]() | ![]() |
Vamos examinar o conteúdo do pacote SwingExtras.jar:

Nele encontramos o código-fonte Java dos componentes oferecidos no pacote. Também encontramos as próprias classes:

Desse arquivo, observamos que a classe JFontChooser, na verdade, se chama com.lamatek.swingextras.JFontChooser. Se não quisermos escrever o nome completo, precisaremos escrever no início do programa:
Como o compilador e a máquina virtual Java encontrarão esse novo pacote? No caso do uso direto do JDK, isso já foi explicado, e o leitor poderá encontrar as explicações no parágrafo sobre os pacotes Java. Detalhamos aqui o método a ser utilizado com o JBuilder. Os pacotes são configurados no menu Opções/Configurar o JDK:

1 | O botão Modifier (1) permite indicar ao JBuilder qual JDK deve ser utilizado. Neste exemplo, o JBuilder trouxe consigo o JDK 1.3.1. Quando o JDK 1.4 foi lançado, ele foi instalado separadamente do JBuilder, e utilizou-se o botão Modifier para indicar ao JBuilder quepassar a utilizar o JDK 1.4, indicando o diretório de instalação deste último |
2 | diretório raiz do JDK, atualmente utilizado pelo JBuilder |
3 | lista dos arquivos Java (.jar) utilizados pelo JBuilder. É possível adicionar outros usando o botão Ajouter (4) |
4 | O botão Ajouter (4) permite adicionar novos pacotes que o JBuilder utilizará tanto para a compilação quanto para a execução dos programas. Ele foi utilizado aqui para adicionar o pacote SwingExtras.jar (5) |
Agora, o JBuilder está configurado corretamente para poder utilizar a classe JFontChooser. No entanto, precisaríamos ter acesso à definição dessa classe para utilizá-la corretamente. O arquivo swingextras.jar contém arquivos HTML que poderíamos extrair para aproveitá-los. Isso é desnecessário. A documentação Java incluída nos arquivos .jar pode ser acessada diretamente a partir do JBuilder. Para isso, é preciso configurar a aba Documentation (6) acima. Aparece a seguinte janela:

O botão Ajouter permite indicar que o arquivo SwingExtras.jar deve ser explorado em busca da documentação. Após a validação dessa configuração, é possível constatar que, de fato, temos acesso à documentação do SwingExtras.jar. Isso traz diversas facilidades:
- se começarmos a escrever a instrução de importação
, perceberemos que o JBuilder nos fornece uma ajuda:

O pacote com.lamatek foi encontrado.
- Agora, no programa a seguir:
Ao digitar F1 na palavra-chave JFontChooser, obtém-se uma ajuda sobre essa classe:

Vemos na barra de status 1 que, de fato, está sendo utilizado um arquivo HTML do pacote swingextras.jar. O exemplo apresentado acima é suficientemente claro para que possamos escrever o código do botão Police do nosso aplicativo:
void btnPolice_actionPerformed(ActionEvent e) {
// seleção de uma fonte de texto usando o componente JFontChooser
jFontChooser1 = new JFontChooser(new Font("Arial", Font.BOLD, 12));
if (jFontChooser1.showDialog(this, "Choix d'une police") == JFontChooser.ACCEPT_OPTION) {
// alteração da fonte dos caracteres da caixa de texto
txtTexte.setFont(jFontChooser1.getSelectedFont());
}//if
}
A caixa de seleção exibida pelo método showDialog acima é a seguinte:

5.5. O aplicativo gráfico IMPOTS
Retomamos a aplicação IMPOTS, já abordada duas vezes. Agora, adicionamos a ela uma interface gráfica:

Os controles são os seguintes
n.º | tipo | nome | função |
1 | JRadioButton | rdOui | marque se for casado |
2 | JRadioButton | rdNon | marque se não for casado |
3 | JSpinner | spinEnfants | número de filhos do contribuinte Mínimo=0, Máximo=20, Incremento=1 |
4 | JTextField | txtSalaire | salário anual do contribuinte em F |
5 | JLabel | lblImpots | valor do imposto a pagar |
6 | JTextField | txtStatus | campo de mensagens de status — não editável |
O menu é o seguinte:
opção principal | opção secundária | nome | função |
Impostos | |||
Inicializar | mnuInitialiser | carrega os dados necessários para o cálculo a partir de um arquivo de texto | |
Calcular | mnuCalculer | calcula o imposto a pagar quando todos os dados necessários estiverem presentes e corretos | |
Apagar | mnuEffacer | recupera o formulário ao seu estado inicial | |
Sair | mnuQuitter | encerra o aplicativo |
Regras de funcionamento
- o menu Calculer permanece desativado enquanto não houver nada no campo do salário
- se, ao iniciar o cálculo, for constatado que o salário está incorreto, o erro é sinalizado:

O programa está apresentado abaixo. Ele utiliza a classe impots criada no capítulo sobre classes. Uma parte do código gerado automaticamente pelo JBuilder não foi reproduzida aqui.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
import java.util.*;
import javax.swing.event.*;
public class frmImpots extends JFrame {
// os componentes da janela
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem mnuInitialiser = new JMenuItem();
JMenuItem mnuCalculer = new JMenuItem();
JMenuItem mnuEffacer = new JMenuItem();
JMenuItem mnuQuitter = new JMenuItem();
JLabel jLabel1 = new JLabel();
JFileChooser jFileChooser1 = new JFileChooser();
JTextField txtStatus = new JTextField();
JRadioButton rdOui = new JRadioButton();
JRadioButton rdNon = new JRadioButton();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSalaire = new JTextField();
JLabel jLabel4 = new JLabel();
JLabel jLabel5 = new JLabel();
JLabel lblImpots = new JLabel();
JLabel jLabel7 = new JLabel();
ButtonGroup buttonGroup1 = new ButtonGroup();
JSpinner spinEnfants=null;
FileFilter filtreTxt=null;
// os atributos da classe
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
//Construir o quadro
public frmImpots() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// outras inicializações
moreInit();
}
// inicialização do formulário
private void moreInit(){
// menu “Calcular” desativado
mnuCalculer.setEnabled(false);
// campos de entrada desativados
txtSalaire.setEditable(false);
txtSalaire.setBackground(Color.WHITE);
// campo de status
txtStatus.setBackground(Color.WHITE);
// spinner Filhos — entre 0 e 20 filhos
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
// filtro *.txt para a caixa de seleção
filtreTxt = new javax.swing.filechooser.FileFilter(){
public boolean accept(File f){
// aceita-se “f”?
return f.getName().toLowerCase().endsWith(".txt");
}//aceitar
public String getDescription(){
// descrição do filtro
return "Fichiers Texte (*.txt)";
}//getDescription
};
// adiciona-se o filtro *.txt
jFileChooser1.addChoosableFileFilter(filtreTxt);
// também queremos o filtro para todos os arquivos
jFileChooser1.setAcceptAllFileFilterUsed(true);
// definimos o diretório inicial da caixa FileChooser
jFileChooser1.setCurrentDirectory(new File("."));
}//moreInit
//Inicializar o componente
private void jbInit() throws Exception {
................
}
//Substituído, assim podemos sair quando a janela for fechada
protected void processWindowEvent(WindowEvent e) {
.....................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// saímos do aplicativo
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// carregamos o arquivo de dados
// que é selecionado com a caixa de seleção JFileChooser1
jFileChooser1.setFileFilter(filtreTxt);
if (jFileChooser1.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION)
return;
// o arquivo selecionado é processado
try{
// leitura dos dados
lireFichier(jFileChooser1.getSelectedFile());
// criação do objeto de impostos
objImpots=new impots(limites,coeffr,coeffn);
// confirmação
txtStatus.setText("Données chargées");
// o salário pode ser alterado
txtSalaire.setEditable(true);
// não é mais possível fazer alterações
mnuInitialiser.setEnabled(false);
}catch(Exception ex){
// problema
txtStatus.setText("Erreur : " + ex.getMessage());
// fim
return;
}//captura
}
private void lireFichier(File fichier) throws Exception {
// as tabelas de dados
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// abertura do arquivo para leitura
BufferedReader IN=new BufferedReader(new FileReader(fichier));
// o arquivo é lido linha por linha
// elas têm o formato limite coeffr coeffn
String ligne=null;
int numLigne=0; // número da linha atual
while((ligne=IN.readLine())!=null){
// mais uma linha
numLigne++;
// a linha é dividida em campos
champs=ligne.split("\\s+");
// 3 campos?
if(champs.length!=3)
throw new Exception("ligne " + numLigne + "erronée dans fichier des données");
// recuperamos os três campos
aLimites.add(champs[0]);
aCoeffR.add(champs[1]);
aCoeffN.add(champs[2]);
}//while
// fechamento do arquivo
IN.close();
// transferência dos dados para tabelas delimitadas
int n=aLimites.size();
limites=new double[n];
coeffr=new double[n];
coeffn=new double[n];
for(int i=0;i<n;i++){
limites[i]=Double.parseDouble((String)aLimites.get(i));
coeffr[i]=Double.parseDouble((String)aCoeffR.get(i));
coeffn[i]=Double.parseDouble((String)aCoeffN.get(i));
}//for
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// cálculo do imposto
// verificação do salário
int salaire=0;
try{
salaire=Integer.parseInt(txtSalaire.getText().trim());
if(salaire<0) throw new Exception();
}catch (Exception ex){
// mensagem de erro
txtStatus.setText("Salaire incorrect. Recommencez");
// foco no campo com erro
txtSalaire.requestFocus();
// retorno à interface
return;
}
// número de filhos
Integer InbEnfants=(Integer)spinEnfants.getValue();
// cálculo do imposto
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),InbEnfants.intValue(),salaire));
// exclusão da mensagem de status
txtStatus.setText("");
}
void txtSalaire_caretUpdate(CaretEvent e) {
// o salário mudou — atualiza-se o menu “calcular”
mnuCalculer.setEnabled(! txtSalaire.getText().trim().equals(""));
}
void mnuEffacer_actionPerformed(ActionEvent e) {
// Limpar o formulário
rdNon.setSelected(true);
spinEnfants.getModel().setValue(new Integer(0));
txtSalaire.setText("");
mnuCalculer.setEnabled(false);
lblImpots.setText("");
}
}
Utilizamos aqui um componente disponível apenas a partir da versão 1.4 do JDK, o JSpinner. Trata-se de um incrementador, que permite ao usuário definir o número de filhos. Esse componente Swing não estava disponível na barra de componentes Swing do JBuilder 6 utilizado para o teste. Isso não impede seu uso, embora o processo seja um pouco mais complicado do que para os componentes disponíveis na barra de componentes. De fato, não é possível arrastar o componente JSpinner para o formulário durante o design. É preciso fazer isso na execução. Vejamos o código que realiza isso:
// spinner Filhos — entre 0 e 20 filhos
spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
spinEnfants.setBounds(new Rectangle(137,60,40,27));
contentPane.add(spinEnfants);
A primeira linha cria o componente JSpinner. Esse componente pode ser utilizado para diversas finalidades, e não apenas como um incrementador de números inteiros, como neste caso. O argumento do construtor JSpinner é, neste caso, um modelo de incrementador de números que aceita quatro parâmetros (valor, mínimo, máximo, incremento). O componente tem a seguinte forma:
![]()
valeur | valor inicial exibido no componente |
min | valor mínimo exibível no componente |
max | valor máximo exibível no componente |
incrément | valor de incremento do valor exibido ao usar as setas para cima/para baixo do componente |
O valor do componente é obtido por meio de seu método getValue, que retorna um tipo Object. Daí a necessidade de algumas conversões de tipo para obter o inteiro de que precisamos:
// número de filhos
Integer InbEnfants=(Integer)spinEnfants.getValue();
// cálculo do imposto
lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),
InbEnfants.intValue(),salaire));
Depois que o componente JSpinner for definido, ele será inserido na janela:
Antes de mais nada, o usuário deve utilizar a opção de menu Initialiser, que cria um objeto impots com o construtor
da classe impots. Vale lembrar que essa classe foi definida como exemplo no capítulo sobre classes. Consulte-o, se necessário. As três tabelas necessárias ao construtor são preenchidas a partir do conteúdo de um arquivo de texto com o seguinte formato:
12620.0 | 0 | 0 |
13190 | 0,05 | 631 |
15.640 | 0,1 | 1.290,5 |
24.740 | 0,15 | 2.072,5 |
31.810 | 0,2 | 3.309,5 |
39.970 | 0,25 | 4.900 |
48.360 | 0,3 | 6.898,5 |
55.790 | 0,35 | 9.316,5 |
92.970 | 0,4 | 12.106 |
127.860 | 0,45 | 16.754,5 |
151.250 | 0,50 | 23.147,5 |
172.040 | 0,55 | 30.710 |
195.000 | 0,60 | 39.312 |
0 | 0,65 | 49.062 |
Cada linha contém três números separados por pelo menos um espaço. Esse arquivo de texto é selecionado pelo usuário por meio de um componente JFileChooser. Depois que o objeto do tipo impots for criado, basta deixar que o usuário forneça as três informações necessárias: casado ou solteiro, número de filhos e salário anual, e chamar o método calculer da classe impots. A operação pode ser repetida várias vezes. O objeto do tipo impots, por sua vez, é criado apenas uma vez, ao utilizar a opção Initialiser.
5.6. Criação de applets
5.6.1. Introdução
Quando se desenvolve um aplicativo com interface gráfica, é bastante fácil transformá-lo em applet. Armazenado em uma máquina A, ele pode ser baixado por meio de um navegador da Web a partir de uma máquina B conectada à Internet. A aplicação inicial é, assim, compartilhada entre vários usuários, e esse é o principal interesse de transformar uma aplicação em applet. No entanto, nem toda aplicação pode ser transformada dessa forma: para não prejudicar o usuário que utiliza um applet em seu navegador, o ambiente do applet é regulamentado:
- um applet não pode ler ou gravar no disco do usuário
- ela só pode se comunicar com o computador a partir do qual foi baixada pelo navegador.
Essas são restrições rigorosas. Elas implicam, por exemplo, que um aplicativo que precise ler informações em um arquivo ou banco de dados deverá solicitá-las por meio de um aplicativo intermediário localizado no servidor de onde foi baixado.
A estrutura geral de um aplicativo da Web simples é a seguinte:

- o cliente solicita um documento HTML ao servidor da Web, geralmente por meio de um navegador. Esse documento pode conter um applet que funcionará como um aplicativo gráfico autônomo dentro do documento HTML exibido pelo navegador do cliente.
- Esse applet poderá ter acesso a dados, mas apenas àqueles localizados no servidor web. Ele não terá acesso nem aos recursos da máquina cliente que o executa, nem aos de outras máquinas da rede, exceto aquela a partir da qual foi baixado.
5.6.2. A classe JApplet
5.6.2.1. Définition
Um aplicativo pode ser baixado por um navegador da Web se for uma instância da classe java.applet.Applet ou da classe javax.swing.JApplet. Esta última deriva da primeira, que por sua vez deriva da classe Panel, que a seu vez deriva da classe Container. Uma instância Applet ou JApplet, sendo do tipo container, poderá, portanto, conter componentes (Component) como botões, caixas de seleção, listas, etc. Vamos dar algumas orientações sobre a função dos diferentes métodos:
Método | Função |
public void destroy(); | destrói a instância do Applet |
public AppletContext getAppletContext(); | recupera o contexto de execução do applet (documento HTML no qual ele se encontra, outros applets do mesmo documento, …) |
public String getAppletInfo(); | retorna uma sequência de caracteres com informações sobre o applet |
public AudioClip getAudioClip(URL url); | carrega o arquivo de áudio especificado por URL |
public AudioClip getAudioClip(URL url, String name); | carrega o arquivo de áudio especificado por URL/name |
public URL getCodeBase(); | retorna o URL do applet |
public URL getDocumentBase(); | retorna o URL do documento HTML que contém o applet |
public Image getImage(URL url); | recupera a imagem especificada por URL |
public Image getImage(URL url, String name); | recupera a imagem especificada por URL/name |
public String getParameter(String name); | recupera o valor do parâmetro name contido na tag <applet> do documento HTML que contém o applet. |
public void init(); | esse método é chamado pelo navegador durante a inicialização do applet |
public boolean isActive(); | estado do applet |
public void play(URL url); | reproduz o arquivo de áudio especificado por URL |
public void play(URL url, String name); | reproduz o arquivo de áudio especificado por UR/name |
public void resize(Dimension d); | define as dimensões da moldura do applet |
public void resize(int width, int height); | idem |
public final void setStub(AppletStub stub); | |
public void showStatus(String msg); | exibe uma mensagem na barra de status do applet |
public void start(); | esse método é chamado pelo navegador sempre que o documento que contém o applet é exibido |
public void stop(); | esse método é chamado pelo navegador sempre que o documento que contém o applet é abandonado em favor de outro (mudança de URL pelo usuário) |
A classe JApplet trouxe algumas melhorias à classe Applet, notadamente a capacidade de conter os componentes JMenuBar e c.a.d. dos menus, o que não era possível com a classe Applet.
5.6.2.2. Execução de um applet: os métodos init, start e stop
Quando um navegador carrega um applet, ele chama três métodos dele:
init | Esse método é chamado durante o carregamento inicial do applet. Portanto, nele serão colocadas as inicializações necessárias para a aplicação. |
start | Esse método é chamado sempre que o documento que contém o applet se torna o documento ativo do navegador. Assim, quando um usuário carrega um applet, os métodos init e start serão executados nessa ordem. Quando ele sair do documento para visualizar outro, o método stop será executado. Quando ele voltar a ele mais tarde, o método start será executado. |
stop | Este método é chamado sempre que o usuário sai do documento que contém o applet. |
Para muitos applets, apenas o método init é necessário. Os métodos start e stop só são necessários se o aplicativo iniciar tarefas (threads) que sejam executadas em paralelo e de forma contínua, muitas vezes sem o conhecimento do usuário. Quando o usuário sai do documento, a parte visível do aplicativo desaparece, mas essas tarefas em segundo plano continuam em execução. Isso geralmente é desnecessário. Aproveita-se, então, a chamada do navegador ao método stop para interrompê-las. Se o usuário retornar ao documento, aproveita-se a chamada do navegador ao método **start** para reiniciá-las.
Tomemos, por exemplo, um applet que possui um relógio em sua interface gráfica. Esse relógio é mantido por uma tarefa em segundo plano (thread). Quando, no navegador, o usuário sai da página do applet, é desnecessário manter o relógio, que se tornou invisível: no método stop do applet, interromperemos o thread que gerencia o relógio. No método **start**, ele será reiniciado para que, quando o usuário voltar à página do applet, encontre um relógio com a hora correta.
5.6.3. Transformação de um aplicativo gráfico em applet
Supõe-se aqui que essa transformação seja possível, ou seja, que ela atenda às restrições de execução dos applets. Um aplicativo é iniciado pelo método main de uma de suas classes:
Essa aplicação é transformada em um applet da seguinte maneira:
import java.applet.JApplet;
…
public class application extends JApplet{
…
public void init(){
…
}
…
}// fim da turma
Observe os seguintes pontos:
- a classe application agora deriva da classe JApplet
- o método main foi substituído pelo método init.
A título de exemplo, voltamos a uma aplicação já estudada: o gerenciamento de listas.

Os componentes desta janela são os seguintes:
n.º | tipo | nome | função |
1 | JTextField | txtSaisie | campo de entrada |
2 | JList | jList1 | lista contida em um contêiner jScrollPane1 |
3 | JList | jList2 | lista contida em um contêiner jScrollPane2 |
4 | JButton | cmd1To2 | transfere os elementos selecionados da lista 1 para a lista 2 |
5 | JButton | cmd2To1 | faz o inverso |
6 | JButton | cmdRaz1 | esvazia a lista 1 |
7 | JButton | cmdRaz2 | esvazia a lista 2 |
A estrutura da aplicação era a seguinte:
public class interfaceAppli extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Construir o quadro*/
public interfaceAppli() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar o componente*/
private void jbInit() throws Exception {
...
txtSaisie.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
txtSaisie_actionPerformed(e);
}
});
...
// Jlist1 é colocado no contêiner jScrollPane1
jScrollPane1.getViewport().add(jList1, null);
// Jlist2 é colocado no contêiner jScrollPane2
jScrollPane2.getViewport().add(jList2, null);
...
}
/**Substituído, para que possamos sair quando a janela for fechada*/
protected void processWindowEvent(WindowEvent e) {
...
}
void txtSaisie_actionPerformed(ActionEvent e) {
.............
}//classe
void cmdRaz1_actionPerformed(ActionEvent e) {
// esvaziar a lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// vaziar lista 2
v2.removeAllElements();
}///comando Raz2
Para transformar a classe appli em applet, é necessário proceder da seguinte forma:
- modificar a classe interfaceAppli anterior para que ela não derive mais de JFrame, mas sim de JApplet:
- excluir a instrução que define o título da janela JFrame. Um applet JApplet não possui barra de título
- Alterar o construtor para um método init e, nesse método, remover o gerenciamento de eventos da janela (WindowListener, ...). Um applet é um contêiner que não pode ser redimensionado nem fechado.
/**Construir o quadro*/
public init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
- O método processWindowEvent deve ser excluído ou colocado entre comentários
/**Substituído, para que possamos sair quando a janela estiver fechada*/
//protected void processWindowEvent(WindowEvent e) {
// super.processWindowEvent(e);
// if (e.getID() == WindowEvent.WINDOW_CLOSING) {
// System.exit(0);
// }
// }
Apresentamos, a título de exemplo, o código completo do applet, exceto a parte gerada automaticamente pelo JBuilder
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceAppli extends JApplet {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
JTextField txtSaisie = new JTextField();
JButton cmd1To2 = new JButton();
JButton cmd2To1 = new JButton();
DefaultListModel v1=new DefaultListModel();
DefaultListModel v2=new DefaultListModel();
JList jList1 = new JList(v1);
JList jList2 = new JList(v2);
JScrollPane jScrollPane1 = new JScrollPane();
JScrollPane jScrollPane2 = new JScrollPane();
JButton cmdRaz1 = new JButton();
JButton cmdRaz2 = new JButton();
JLabel jLabel4 = new JLabel();
/**Construir a estrutura*/
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//interfaceAppli
/**Inicializar o componente*/
private void jbInit() throws Exception {
//setIconImage(Toolkit.getDefaultToolkit().createImage(interfaceAppli.class.getResource("[Votre icône]")));
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(400, 308));
// this.setTitle("JList");
jScrollPane1.setBounds(new Rectangle(37, 133, 124, 101));
jScrollPane2.setBounds(new Rectangle(232, 132, 124, 101));
.............
}
void txtSaisie_actionPerformed(ActionEvent e) {
// o texto inserido foi validado
// ele é recuperado sem os espaços no início e no final
String texte=txtSaisie.getText().trim();
// se estiver vazio, não é aceito
if(texte.equals("")){
// mensagem de erro
JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
"Erreur",JOptionPane.WARNING_MESSAGE);
// fim
return;
}//se
// se não estiver vazio, adiciona-se aos valores da lista 1
v1.addElement(texte);
// e esvazia-se o campo de entrada
txtSaisie.setText("");
}
void cmd1To2_actionPerformed(ActionEvent e) {
// transferência dos elementos selecionados da lista 1 para a lista 2
transfert(jList1,jList2);
}//cmd1To2
private void transfert(JList L1, JList L2){
// transferência dos elementos selecionados da lista 1 para a lista 2
// recupera-se a matriz de índices dos elementos selecionados em L1
int[] indices=L1.getSelectedIndices();
// o que fazer?
if (indices.length==0) return;
// recuperam-se os valores de L1
DefaultListModel v1=(DefaultListModel)L1.getModel();
// e os de L2
DefaultListModel v2=(DefaultListModel)L2.getModel();
for(int i=indices.length-1;i>=0;i--){
// adicionamos a L2 os valores selecionados em L1
v2.addElement(v1.elementAt(indices[i]));
// os elementos de L1 copiados para L2 devem ser excluídos de L1
v1.removeElementAt(indices[i]);
}//para
}//transferência
private void affiche(String message){
// exibe mensagem
JOptionPane.showMessageDialog(this,message,
"Suivi",JOptionPane.INFORMATION_MESSAGE);
}// exibe
void cmd2To1_actionPerformed(ActionEvent e) {
// transfere os elementos selecionados de jList2 para jList1
transfert(jList2,jList1);
}//cmd2TO1
void cmdRaz1_actionPerformed(ActionEvent e) {
// limpar a lista 1
v1.removeAllElements();
}//comando Raz1
void cmdRaz2_actionPerformed(ActionEvent e) {
// vaziar lista 2
v2.removeAllElements();
}//comando Raz2
}//classe
É possível compilar o código-fonte deste applet. Fazemos isso aqui com o JDK, sem o JBuilder.
E:\data\serge\Jbuilder\interfaces\JApplets\1>javac.bat interfaceAppli.java
E:\data\serge\Jbuilder\interfaces\JApplets\1>dir
12/06/2002 16:40 6 148 interfaceAppli.java
12/06/2002 16:41 527 interfaceAppli$1.class
12/06/2002 16:41 525 interfaceAppli$2.class
12/06/2002 16:41 525 interfaceAppli$3.class
12/06/2002 16:41 525 interfaceAppli$4.class
12/06/2002 16:41 525 interfaceAppli$5.class
12/06/2002 16:41 4 759 interfaceAppli.class
O aplicativo pode ser testado com o programa AppletViewer do JDK, que permite executar applets ou um navegador. Para isso, é necessário criar o documento HTML appli.htm, que conterá o applet:
<html>
<head>
<title>listes swing</title>
</head>
<body>
<applet
code="interfaceAppli.class"
width="400"
height="300">
</applet>
</body>
</html>
Temos aqui um documento HTML clássico, exceto pela presença da tag applet. Ela foi utilizada com três parâmetros:
code="interfaceAppli.class" | nome da classe JAVA compilada a ser carregada para executar o applet |
width="400" | largura do quadro do applet no documento |
height="300" | altura do quadro do applet no documento |
Depois que o arquivo appli.htm for gravado, ele poderá ser carregado com o programa appletviewer do JDK ou com um navegador. Digite o seguinte comando em uma janela do DOS, na pasta do arquivo appli.htm:
appletviewer appli.htm
Supõe-se aqui que o diretório do executável appletviewer.exe esteja no PATH da janela do DOS; caso contrário, seria necessário especificar o caminho completo do executável appletviewer.exe. Aparece a seguinte janela:

Interrompemos a execução do applet com a opção Applet/Quitter. Vamos agora testar o applet com um navegador. Este deve utilizar uma máquina virtual Java 2 para poder exibir os componentes Swing. Até recentemente (2001), essa restrição representava um problema, pois a Sun produzia JDK que os desenvolvedores de navegadores só adotavam com grande atraso. Por fim, a Sun eliminou esse obstáculo ao disponibilizar aos usuários um aplicativo chamado “Java plugin”, que permite que os navegadores Internet Explorer e Netscape Navigator utilizem as versões mais recentes do JRE produzidas pela Sun (JRE = Java Runtime Environment). Os testes a seguir foram realizados com o IE 5.5 equipado com o plugin Java 1.4.
Uma primeira maneira de testar o applet interfaceAppli.class é carregar o arquivo HTML appli.htm diretamente no navegador, clicando duas vezes nele. O navegador exibe então a página HTML e seu applet sem a necessidade de um servidor web:

Pelo URL (1), percebe-se que o arquivo foi carregado diretamente no navegador. No exemplo a seguir, o arquivo appli.htm foi solicitado a um servidor Web Apache operando na porta 81 da máquina local:

5.6.4. A opção de formatação <applet> em um documento HTML
Vimos que, em um documento HTML, o applet era referenciado pela tag de formatação <applet>. Essa tag pode ter diversos parâmetros:
<applet
code=
width=
height=
codebase=
align=
hspace=
vspace=
alt=
>
<param name1=nom1 value=val1>
<param name2=nom2 value=val2>
texte
>
</applet>
O significado dos parâmetros é o seguinte:
Parâmetro | Significado |
code | obrigatório — nome do arquivo .class a ser executado |
width | obrigatório - largura do applet no documento |
height | obrigatório - altura … |
codebase | opcional - URL do diretório que contém o applet a ser executado. Se codebase não for especificado, o applet será procurado no diretório do documento HTML que o referencia |
align | opcional - posicionamento (LEFT, RiGHT, CENTER) do applet no documento |
hspace | opcional — margem horizontal ao redor do applet, expressa em pixels |
vspace | opcional — margem vertical ao redor do applet, expressa em pixels |
alt | opcional — texto exibido no lugar do applet caso o navegador não consiga carregá-lo |
param | opcional — parâmetro passado ao applet especificando seu nome (name) e seu valor (value). O applet poderá recuperar o valor do parâmetro nome1 por meio de val1=getParameter("nome1") É possível usar quantos parâmetros forem desejados |
texte | opcional — será exibido por qualquer navegador incapaz de executar um applet, por exemplo, por não possuir uma máquina virtual Java. |
Vejamos um exemplo para ilustrar a passagem de parâmetros para um applet:
<html>
<head>
<title>paramètres applet</title>
</head>
<body>
<applet code="interfaceParams.class" width="400" height="300">
<param name="param1" value="val1">
<param name="param2" value="val2">
</applet>
</body>
</html>
O código Java do applet interfaceParams foi gerado conforme indicado anteriormente. Criamos um aplicativo JBuilder e, em seguida, realizamos as poucas alterações mencionadas acima:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class interfaceParams extends JApplet {
JPanel contentPane;
JScrollPane jScrollPane1 = new JScrollPane();
JLabel jLabel1 = new JLabel();
DefaultListModel params=new DefaultListModel();
JList lstParams = new JList(params);
//Construir o quadro
public void init() {
// enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// outras inicializações
moreInit();
}
// inicializações
public void moreInit(){
// exibe os valores dos parâmetros do applet
params.addElement("nom=param1 valeur="+getParameter("param1"));
params.addElement("nom=param2 valeur="+getParameter("param2"));
}//mais inicializações
//Inicializar o componente
private void jbInit() throws Exception {
............
this.setSize(new Dimension(205, 156));
//this.setTitle("Parâmetros de um applet");
jScrollPane1.setBounds(new Rectangle(19, 53, 160, 73));
............
}
}
A execução com AppletViewer:

5.6.5. Acessar recursos remotos a partir de um applet
Muitos aplicativos precisam utilizar informações contidas em arquivos ou bancos de dados. Já mencionamos que um applet não tem acesso aos recursos da máquina na qual é executado. Essa é uma medida de bom senso. Caso contrário, bastaria escrever um applet para “espionar” o disco dos usuários que o carregam. No entanto, o applet tem acesso aos recursos do servidor do qual foi baixado, por exemplo, arquivos. É isso que veremos agora.
5.6.5.1. A classe URL
Qualquer aplicativo Java pode ler um arquivo presente em uma máquina da rede graças à classe java.net.URL (URL = Uniform Resource Locator). Um URL identifica um recurso da rede, a máquina na qual ele se encontra, bem como o protocolo e a porta de comunicação a serem utilizados para recuperá-lo, no formato:
protocolo:porta//máquina/arquivo
Assim, o URL http://www.ibm.com/index.html designa o arquivo index.html da máquina www.ibm.com. Ele pode ser acessado pelo protocolo http. A porta não é especificada: o navegador utilizará a porta 80, que é a porta padrão do serviço HTTP.
Vamos detalhar alguns dos elementos da classe URL:
public URL(String spec) | cria uma instância de URL a partir de uma string do tipo “protocolo:porta//máquina/arquivo” — lança uma exceção se a sintaxe da string não corresponder a um URL |
public String getFile() | permite obter o campo “arquivo” da string “protocolo:porta//máquina/arquivo” do URL |
public String getHost() | permite obter o campo máquina da string “protocolo:porta//máquina/arquivo” do URL |
public String getPort() | permite obter o campo porta da string “protocolo:porta//máquina/arquivo” do URL |
public String getProtocol() | permite obter o campo protocolo da string "protocolo:porta//máquina/arquivo" do URL |
public URLConnection openConnection() | abre a conexão com a máquina remota getHost() em sua porta getPort(), de acordo com o protocolo getProtocol(), com o objetivo de ler o arquivo getFile(). Lança uma exceção se não for possível abrir a conexão |
public final InputStream openStream() | abreviação para openConnection().getInputStream(). Permite obter um fluxo de entrada a partir do qual o conteúdo do arquivo getFile() poderá ser lido. Lança uma exceção se o fluxo não puder ser obtido |
public String toString() | exibe a identidade da instância de URL |
Há aqui dois métodos que nos interessam:
- public URL(String spec) para especificar o arquivo a ser processado
- public final InputStream openStream() para processá-lo
5.6.5.2. Um exemplo de console
Vamos escrever um programa em Java, sem interface gráfica, encarregado de exibir na tela o conteúdo de um URL que lhe for passado como parâmetro. Um exemplo de chamada poderia ser o seguinte:
O programa é relativamente simples:
import java.net.*; // para a classe URL
import java.io.*; // para os fluxos (stream)
public class urlcontenu{
// exibe o conteúdo do URL passado como argumento
// esse conteúdo deve ser texto para que seja legível
public static void main (String arg[]){
// verificação dos argumentos
if(arg.length==0){
System.err.println("Syntaxe pg url");
System.exit(0);
}
try{
// criação do URL
URL url=new URL(arg[0]);
// leitura do conteúdo
try{
// criação do fluxo de entrada
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
try{
// leitura das linhas de texto no fluxo de entrada
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
} catch (Exception e){
System.err.println("Erreur lecture : " +e);
}
finally{
try { is.close(); } catch (Exception e) {}
}
} catch (Exception e){
System.err.println("Erreur openStream : " +e);
}
} catch (Exception e){
System.err.println("Erreur création URL : " +e);
}
}// fim da função main
}// fim da classe
Após verificar se havia realmente um argumento, tentamos criar um URL com ele:
// criação do URL
URL url=new URL(arg[0]);
Essa criação pode falhar se o argumento não respeitar a sintaxe dos URL protocole:port//machine/fichier. Se houver um URL com sintaxe correta, tenta-se criar um fluxo de entrada a partir do qual será possível ler linhas de texto. O fluxo de entrada fornecido por um URL URL.openStream() fornece um fluxo do tipo InputStream, que é um fluxo orientado por caracteres: a leitura é feita caractere por caractere e é necessário formar as linhas manualmente. Para poder ler linhas de texto, é preciso utilizar o método readLine das classes BufferedReader ou DataInputStream.On; neste caso, escolheu-se BufferedReader. Resta-nos apenas transformar o fluxo InputStream do URL no fluxo BufferedReader. Isso é feito criando-se um fluxo intermediário InputStreamReader:
BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
A criação desse fluxo pode falhar. A exceção correspondente é tratada. Uma vez obtido o fluxo, basta ler as linhas de texto nele contidas e exibi-las na tela.
String ligne;
while((ligne=is.readLine())!=null)
System.out.println(ligne);
Mais uma vez, a leitura pode gerar uma exceção que deve ser tratada. Aqui está um exemplo de execução do programa que requer uma instância local de URL:
E:\data\serge\Jbuilder\interfaces\JApplets\3>java urlcontenu http://localhost
<html>
<head>
<title>Bienvenue dans le Serveur Web personnel</title>
</head>
<body bgcolor="#FFFFFF" link="#0080FF" vlink="#0080FF"
topmargin="0" leftmargin="0">
<table border="0" cellpadding="0" cellspacing="0" width="100%"
bgcolor="#000000">
............
</table>
</center></div></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
5.6.5.3. Um exemplo gráfico
A interface gráfica será a seguinte:

Número | Nome | Tipo | Função |
1 | txtURL | JTextField | URL – a ser lido |
2 | btnCharger | JButton | botão para iniciar a reprodução do URL |
3 | JScrollPane1 | JScrollPane | painel rolante |
4 | lstURL | JList | lista exibindo o conteúdo do URL solicitado |
Ao executar, obtemos um resultado semelhante ao do programa de console:

O código relevante do aplicativo é o seguinte:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.io.*;
public class interfaceURL extends JFrame {
JPanel contentPane;
JLabel jLabel1 = new JLabel();
JTextField txtURL = new JTextField();
JButton btnCharger = new JButton();
JScrollPane jScrollPane1 = new JScrollPane();
DefaultListModel lignes=new DefaultListModel();
JList lstURL = new JList(lignes);
//Construir o quadro
public interfaceURL() {
..............
}
//Inicializar o componente
private void jbInit() throws Exception {
..............
}
//Substituído, para que possamos sair quando a janela for fechada
protected void processWindowEvent(WindowEvent e) {
...................
}
void txtURL_caretUpdate(CaretEvent e) {
// define o estado do botão Carregar
btnCharger.setEnabled(! txtURL.getText().trim().equals(""));
}
void btnCharger_actionPerformed(ActionEvent e) {
// exibe o conteúdo do URL na lista
try{
afficherURL(txtURL.getText().trim());
}catch(Exception ex){
// exibe uma mensagem de erro
JOptionPane.showMessageDialog(this,"Erreur : " + ex.getMessage(),"Erreur",JOptionPane.ERROR_MESSAGE);
}//try-catch
}
private void afficherURL(String strURL) throws Exception {
// exibe o conteúdo de URL strURL na lista
// nenhuma exceção é tratada especificamente. Elas são simplesmente repassadas
// criação do URL
URL url=new URL(strURL);
// criação do fluxo de entrada
BufferedReader IN=new BufferedReader(new InputStreamReader(url.openStream()));
// leitura das linhas de texto no fluxo de entrada
String ligne;
while((ligne=IN.readLine())!=null)
lignes.addElement(ligne);
// fechamento do fluxo de leitura
IN.close();
}
}
5.6.5.4. Um applet
O aplicativo gráfico anterior foi transformado em um applet, conforme já foi apresentado várias vezes. O applet é inserido em um documento HTML appliURL.htm:
<html>
<head>
<title>Applet lisant une URL</title>
</head>
<body>
<h1>Applet lisant une URL</h1>
<applet
code="appletURL.class"
width="400"
height="300"
>
</applet>
</body>
</html>

No exemplo acima, o navegador solicitou o http://localhost:81/Japplets/2/appliURL.htm URL a um servidor web apache operando na porta 81. O applet foi então exibido no navegador. Nele, solicitou-se novamente o URL http://localhost:81/Japplets/2/appliURL.htm para verificar se realmente estávamos obtendo o arquivo appliURL.htm que havíamos criado. Agora, vamos tentar carregar um URL que não pertença à máquina que forneceu o applet (neste caso, localhost):

O carregamento do URL foi recusado. Aqui, vemos novamente a restrição relacionada aos applets: eles só podem acessar os recursos de rede da máquina a partir da qual foram baixados. Existe uma maneira de o applet contornar essa restrição, que é delegar as solicitações de rede a um programa servidor localizado na máquina de onde ele foi baixado. Esse programa fará as solicitações de rede no lugar do applet e lhe enviará os resultados. Isso é chamado de programa intermediário.
5.7. O applet IMPOTS
Vamos agora transformar o aplicativo gráfico IMPOTS em um applet. Isso apresenta um certo interesse: o aplicativo ficará disponível para qualquer usuário da Internet que possua um navegador e um plug-in Java 1.4 (devido ao componente JSpinner). Nosso aplicativo passa, assim, a ter alcance global... Essa modificação exigirá um pouco mais do que a simples transformação de aplicativo gráfico em applet, que já se tornou um procedimento clássico. O aplicativo utiliza uma opção de menu Initialiser cujo objetivo é ler o conteúdo de um arquivo local. No entanto, se pensarmos em um aplicativo web, percebemos que esse esquema não se aplica mais:

É evidente que os dados que definem as tabelas de impostos estarão no servidor web e não em cada uma das máquinas clientes. O arquivo a ser lido no servidor web será, neste caso, colocado na mesma pasta que o applet, e a opção Initialiser deverá buscá-lo nesse local. Os exemplos anteriores mostraram como fazer isso. Além disso, para selecionar o arquivo de dados localmente, utilizávamos um componente JFileChooser, que aqui já não tem mais razão de ser.
O documento HTML contendo o applet será o seguinte:
<html>
<head>
<title>Applet de calcul d'impôts</title>
</head>
<body>
<h2>Calcul d'impôts</h2>
<applet
code="appletImpots.class"
width="320"
height="270"
>
<param name="data" value="impots.txt">
Observe-se o parâmetro data, cujo valor é o nome do arquivo que contém os dados da tabela de impostos. O documento HTML, a classe appletImpots, a classe impots e o arquivo impots.txt estão todos na mesma pasta do servidor web:
E:\data\serge\web\JApplets\impots>dir
12/06/2002 13:24 247 impots.txt
13/06/2002 10:17 654 appletImpots$2.class
13/06/2002 10:17 653 appletImpots$3.class
13/06/2002 10:17 653 appletImpots$4.class
13/06/2002 10:17 651 appletImpots$5.class
13/06/2002 10:06 651 appletImpots$6.class
13/06/2002 10:17 8 655 appletImpots.class
13/06/2002 10:17 657 appletImpots$1.class
13/06/2002 10:24 286 appletImpots.htm
13/06/2002 10:17 1 305 impots.class
O código do applet é o seguinte (destacamos apenas as alterações em relação ao aplicativo gráfico):
...........
import java.net.*;
import java.applet.Applet;
public class appletImpots extends JApplet {
// os componentes da janela
JPanel contentPane;
............................
// os atributos da classe
double[] limites=null;
double[] coeffr=null;
double[] coeffn=null;
impots objImpots=null;
String urlDATA=null;
//Construir o quadro
public void init() {
//enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
// outras inicializações
moreInit();
}
// inicialização do formulário
private void moreInit(){
// menu “Calcular” desativado
mnuCalculer.setEnabled(false);
................
// recuperando o nome do arquivo da tabela de impostos
String nomFichier=getParameter("data");
// erro?
if(nomFichier==null){
// mensagem de erro
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// a opção Inicializar é bloqueada
mnuInitialiser.setEnabled(false);
// fim
return;
}//if
// definindo o URL dos dados
urlDATA=getCodeBase()+"/"+nomFichier;
}//moreInit
//Inicializar o componente
private void jbInit() throws Exception {
...................
}
void mnuQuitter_actionPerformed(ActionEvent e) {
// sair do aplicativo
System.exit(0);
}
void mnuInitialiser_actionPerformed(ActionEvent e) {
// carregando o arquivo de dados
try{
// leitura dos dados
lireDATA();
// criação do objeto “impostos”
objImpots=new impots(limites,coeffr,coeffn);
................
}
private void lireDATA() throws Exception {
// as tabelas de dados
ArrayList aLimites=new ArrayList();
ArrayList aCoeffR=new ArrayList();
ArrayList aCoeffN=new ArrayList();
String[] champs=null;
// abrindo o arquivo para leitura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
// leitura do arquivo linha por linha
....................
}
void mnuCalculer_actionPerformed(ActionEvent e) {
// cálculo do imposto
......................
}
void txtSalaire_caretUpdate(CaretEvent e) {
..........
}
void mnuEffacer_actionPerformed(ActionEvent e) {
...............
}
}
Aqui, comentamos apenas as alterações decorrentes do fato de que o arquivo de dados a ser lido agora está em uma máquina remota, em vez de em uma máquina local:
O nome do arquivo de dados a ser lido, URL, é obtido pelo código a seguir:
// recuperação do nome do arquivo da tabela de impostos
String nomFichier=getParameter("data");
// erro?
if(nomFichier==null){
// mensagem de erro
txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
// bloqueia-se a opção Inicializar
mnuInitialiser.setEnabled(false);
// fim
return;
}//if
// definindo o URL dos dados
urlDATA=getCodeBase()+"/"+nomFichier;
Lembre-se de que o nome do arquivo “impots.txt” foi passado para o parâmetro data do applet:
O código acima, portanto, começa recuperando o valor do parâmetro data, lidando com um possível erro. Se o URL do documento HTML que contém o applet for http://localhost:81/JApplets/impots/appletImpots.htm, o URL do arquivo impots.txt será http://localhost:81/JApplets/impots/impots.txt. Precisamos construir o nome desse URL. O método getCodeBase() do applet fornece o URL da pasta onde foi recuperado o documento HTML contendo o applet, portanto, no nosso exemplo, http://localhost:81/JApplets/impots. A instrução a seguir permite, assim, construir o URL do arquivo de dados:
No método lireFichier(), que lê o conteúdo do URL e do urlData, encontra-se a criação do fluxo de entrada que permitirá a leitura dos dados:
// abertura do arquivo para leitura
BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
A partir daí, não é mais possível distinguir se os dados provêm de um arquivo remoto ou local. Aqui está um exemplo de execução do applet:

5.8. Conclusão
Este capítulo apresentou
- uma introdução à criação de interfaces gráficas com o JBuilder
- os componentes Swing mais comuns
- a criação de applets
Vale lembrar que
- o código gerado pelo JBuilder pode ser escrito manualmente. Uma vez obtido esse código de uma forma ou de outra, basta um simples JDK para executá-lo, e o JBuilder deixa de ser indispensável.
- o uso de uma ferramenta como o JBuilder pode trazer ganhos significativos de produtividade:
- embora seja possível escrever manualmente o código gerado pelo JBuilder, isso pode levar muito tempo e não apresenta grande interesse, já que a lógica da aplicação geralmente está em outro lugar.
- O código gerado pode ser instrutivo. Lê-lo e estudá-lo é uma boa maneira de descobrir certos métodos e propriedades de componentes que estamos usando pela primeira vez.
- O JBuilder é multiplataforma. Assim, mantém-se o conhecimento adquirido ao mudar de uma plataforma para outra. Ser capaz de escrever programas que funcionem tanto no Windows quanto no Linux é, obviamente, um fator de produtividade muito importante. Mas isso se deve ao próprio Java e não ao JBuilder.
5.9. JBuilder no Linux
Todos os exemplos anteriores foram testados no Windows 98. É possível questionar se os programas escritos são portáveis, tal como estão, para o Linux. Desde que a máquina Linux em questão possua as classes utilizadas pelos diferentes programas, eles são portáveis. Se, por exemplo, você instalou o JBuilder no Linux, as classes necessárias já estão na sua máquina. Veja, por exemplo, o resultado da execução de um de nossos programas no componente JList com o JBuilder 4 no Linux:
Apresentamos a seguir a instalação do JBuilder 4 Foundation em uma máquina Linux. Sua instalação em uma máquina Win9x não apresenta nenhum problema e é semelhante ao processo que será descrito a seguir. A instalação de versões posteriores provavelmente será diferente, mas este documento pode, mesmo assim, fornecer algumas informações úteis.
O JBuilder está disponível no site da Inprise no endereço http://www.inprise.com/jbuilder

Nessa página, encontram-se os links para Windows e Linux, entre outros. Descreveremos agora a instalação do JBuilder em um computador Linux que possua a interface gráfica KDE.
Ao clicar no link “Jbuilder 4 for Linux”, é exibido um formulário. Preencha-o e, ao final, você receberá dois arquivos:
jb4docs_fr.tar.gz: a documentação e os exemplos do JBuilder 4
jb4fndlinux_fr.tar.gz: JBuilder 4 Foundation. Trata-se de uma versão limitada do JBuilder 4 comercial, mas suficiente para fins educacionais.
Uma chave de ativação do software será enviada a você por e-mail. Ela permitirá que você utilize o JBuilder 4 e será solicitada logo na primeira vez que o programa for utilizado. Caso perca essa chave, você pode retornar ao link acima e clicar em “get your activation key”. A partir daqui, vamos supor que você seja o root e que esteja no diretório dos dois arquivos tar.gz mencionados acima. Descompacte os dois arquivos:
[ls -l]
drwxr-xr-x 3 nobody nobody 4096 oct 10 2000 docs
drwxr-xr-x 3 nobody nobody 4096 déc 5 13:00 foundation
[ls -l foundation]
-rw-r--r-- 1 nobody nobody 1128 déc 5 13:00 deploy.txt
-rwxr-xr-x 1 nobody nobody 69035365 déc 5 13:00 fnd_linux_install.bin
drwxr-xr-x 2 nobody nobody 4096 déc 5 13:00 images
-rw-r--r-- 1 nobody nobody 15114 déc 5 13:00 index.html
-rw-r--r-- 1 nobody nobody 23779 déc 5 13:00 license.txt
-rw-r--r-- 1 nobody nobody 75739 déc 5 13:00 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 déc 5 13:00 whatsnew.html
[ls -l docs]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
Nos dois diretórios gerados, o arquivo .bin é o arquivo de instalação. Além disso, use um navegador para abrir o arquivo index.html em cada um dos diretórios. Eles fornecem as instruções para instalar os dois produtos. Vamos começar instalando o JBuilder Foundation:
Aparece a primeira tela da instalação. Seguir-se-ão muitas outras:

Confirme. Em seguida, aparece uma tela com explicações:

Execute [suivant].

Aceite o contrato de licença e execute o comando [suivant].

Aceite o local proposto para o JBuilder (anote-o, pois você precisará dele mais tarde) e execute [suivant]. A instalação é rápida.

Estamos prontos para um primeiro teste. No KDE, abra o gerenciador de arquivos para acessar o diretório dos executáveis do JBuilder: /opt/jbuilder4/bin (se você instalou o JBuilder no /opt/jbuilder4):

Clique no ícone jbuilder acima. Como é a primeira vez que você usa o JBuilder, será necessário inserir sua chave de ativação:

Preencha os campos Nom e Société. Selecione [Ajouter] para inserir sua chave de ativação. Lembramos que ela deve ter sido enviada a você por e-mail e que, caso a tenha perdido, você pode obtê-la no endereço da web onde baixou o JBuilder 4 (consulte o início da instalação). Assim que sua chave de ativação for aceita, as condições da licença serão exibidas:

Ao digitar OK, você retorna à janela de inserção de informações já vista anteriormente:

Digite OK para concluir esta etapa, que só é executada na primeira vez. Em seguida, aparece o ambiente de desenvolvimento do JBuilder:

Saia do JBuilder para instalar agora a documentação. Ela instalará alguns arquivos que serão utilizados na ajuda do JBuilder, ajuda que, por enquanto, está incompleta. Volte ao diretório onde você descompactou os arquivos tar.gz do JBuilder. O programa de instalação está no diretório docs. Navegue até ele:
[cd docs]
[ls -l]
-rw-r--r-- 1 nobody nobody 1128 oct 10 2000 deploy.txt
-rwxr-xr-x 1 nobody nobody 40497874 oct 10 2000 doc_install.bin
drwxr-xr-x 2 nobody nobody 4096 oct 10 2000 images
-rw-r--r-- 1 nobody nobody 9210 oct 10 2000 index.html
-rw-r--r-- 1 nobody nobody 23779 oct 10 2000 license.txt
-rw-r--r-- 1 nobody nobody 75739 oct 10 2000 release_notes.html
-rw-r--r-- 1 nobody nobody 31902 oct 10 2000 whatsnew.html
O arquivo de instalação é doc_install.bin, mas não é possível executá-lo imediatamente. Se isso for feito, a instalação falhará sem que se saiba o motivo. Leia o arquivo index.html em um navegador para obter uma descrição detalhada do processo de instalação. O instalador precisa de uma máquina virtual Java, mais precisamente um programa chamado java, e este deve estar no diretório PATH do seu computador. Lembramos que PATH é uma variável do Unix cujo valor, na forma rep1:rep2:...:repn, indica os diretórios repi que devem ser pesquisados na busca por um executável. Neste caso, o instalador solicita a execução de um programa java. Você pode ter várias versões desse programa, dependendo do número de máquinas virtuais Java que tiver instaladas aqui ou ali. Logicamente, usaremos a versão fornecida pelo JBuilder 4, que se encontra em /opt/jbuilder4/jdk1.3/bin. Para definir esse diretório na variável PATH:
[echo $PATH]
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[export PATH=/opt/jbuilder4/jdk1.3/bin/:$PATH]
[echo $PATH]
/opt/jbuilder4/jdk1.3/bin/:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
Agora podemos iniciar a instalação da documentação:
Será realizada uma instalação gráfica:

Ela é muito semelhante à do JBuilder Foundation. Por isso, não entraremos em detalhes. Há uma tela que você não deve deixar de ver:

Normalmente, o instalador deve identificar automaticamente onde você instalou o JBuilder Foundation. Portanto, não altere a opção sugerida, a menos, é claro, que ela esteja incorreta.
Assim que a documentação estiver instalada, estaremos prontos para um novo teste do JBuilder. Inicie o aplicativo conforme mostrado acima. Quando o JBuilder estiver aberto, selecione a opção Ajuda/Tópico de ajuda. No painel à esquerda, clique no link Tutoriels:

O JBuilder vem com um conjunto de tutoriais que permitirão que você comece a programar em Java. Abaixo, seguimos o tutorial “Construção de um aplicativo” mencionado acima.

No JBuilder, selecione Arquivo/Novo projeto. Um assistente exibirá três telas:

Vamos criar uma janela simples com o título “Olá a todos”. Chamaremos esse projeto de coucou. O exemplo foi executado pelo root. O JBuilder sugere, então, agrupar todos os projetos em um diretório jbproject, localizado no diretório de conexão do root. O projeto coucou será colocado no diretório coucou (campo “Nome do diretório do projeto”) de jbproject. Execute o [suivant].

Esta segunda tela é um resumo dos diferentes caminhos do seu projeto. Não há nada a ser alterado. Execute [suivant].

A terceira tela solicita que você personalize seu projeto. Preencha e execute [Terminer].
Agora execute Fichier/Nouveau:

Selecione Application e execute OK. Um novo assistente exibirá duas telas:

O campo paquet contém o nome do projeto. O campo “classe” solicita o valor nom, que será atribuído à classe principal do projeto. Pegue o nome acima e insira [suivant]:

Nosso aplicativo possui uma segunda classe Java para a janela do aplicativo. Dê um nome a essa classe. O campo Titre é o título que você deseja atribuir a essa janela. O quadro options oferece opções para sua janela. Selecione todas elas e defina como [Terminer]. Você retornará então ao ambiente JBuilder, que agora conta com as informações que você forneceu para o seu projeto:

Na janela à esquerda/em cima (1), você tem a lista dos arquivos que compõem seu projeto. Nela estão, entre outros, as duas classes .java, às quais acabamos de dar nome. Na janela à direita (2), você tem o código Java da classe coucouCadre. Na janela à esquerda/parte inferior, você vê a estrutura (classes, métodos, atributos) do seu projeto. Ele está pronto para ser executado. Clique no botão 4 acima, selecione Executar/Executar o projeto ou selecione F9. Você deverá ver a seguinte janela:

Ao clicar na opção Aide, você deverá encontrar as informações que forneceu aos assistentes de criação. Não iremos além disso. Agora é hora de mergulhar nos tutoriais.
Antes de encerrar, vamos apenas mostrar que você pode usar não o JBuilder e sua interface gráfica, mas o JDK que ele trouxe consigo e instalou em /opt/jbuilder4/jdk1.3. Compile o seguinte arquivo essai1.java:
import java.io.*;
public class essai1{
public static void main(String args[]){
System.out.println("coucou");
System.exit(0);
}
}
Vamos compilar e executar com o JDK do JBuilder:






