Skip to content

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:

Image

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:

java form1

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:

Image

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-á:

conteneur.add(C)

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:

    setLayout(objet XXXLayout);

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:

    setLayout(null);

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:

Image

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

Image

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:

Image

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

Image

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:

Image

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:

    f1.addMouseListener(new gestionnaireSouris());

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.

  1. Inicie o JBuilder e selecione a opção Arquivo/Novo projeto. A primeira página de um assistente será exibida:

Image

  1. 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]

  1. Uma tela confirma as opções da etapa anterior

Image

Execute [suivant]

  1. Uma nova tela solicita que você defina as características do seu projeto:

Image

Execute [terminer]

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

Image

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

Image

No campo classe, insira o nome da classe que será criada. Aqui, usamos o mesmo nome do projeto.

Execute [suivant]

  1. A tela a seguir é exibida:

Image

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]

  1. É 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

Image

  • 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:

Image

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:

Image

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:

Image

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:

Image

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:

  1. a função main define a aparência da janela (setLookAndFeel) e cria uma instância da classe début.
  2. 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.
  3. 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.
  4. 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:

Image

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

Image

O arquivo début2.java é reduzido à sua forma mais simples:

public class début2 {
}

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

Image

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

Image

Selecione début2 e altere para [OK].

Image

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
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

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 contentPane;
  BorderLayout borderLayout1 = new BorderLayout();

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");
  }
  1. O desenvolvedor começa informando que irá gerenciar os eventos na janela (enableEvents) e, em seguida, chama o método jbInit.
  2. O contêiner (JPanel) da janela (JFrame) é obtido (getContentPane)
  3. O gerenciador de formatação é definido (setLayout)
  4. O tamanho da janela é definido (setSize)
  5. 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:

Image

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.

Image

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

Image

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:

Image

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:

Image

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:

Image

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:

Image

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

Image

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:

Image

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.

Image

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:

Image

e a seguinte estrutura:

Image

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

Image

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.

Image

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:

Image

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:

  void cmdAfficher_actionPerformed(ActionEvent e) {
 }

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:

Image

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

Image

Image

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:

cmdAfficher.addActionListener(this)

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.

Image

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:

Image

Vamos examinar mais de perto as páginas Sommaire e Index.

5.2.4.1. Ajuda: Índice

Image

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:

Image

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:

Image

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:

Image

A ajuda exibirá as entradas do índice que começam com o texto digitado:

Image

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

Image

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:

Image

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:

Image

5.2.5.2. componente JComboBox

Image

Image

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.

Image

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
  JScrollPane jScrollPane1 = new JScrollPane();
  • e, em seguida, no código de jbInit, a lista é associada ao contêiner
    jScrollPane1.getViewport().add(jList1, null);

Para adicionar valores à lista JList1 acima, basta adicioná-los ao seu vetor de valores valeurs:

    // inicializar lista
    for(int i=0;i<10;i++)
      valeurs.addElement(""+i);

e, então, obtém-se a seguinte janela:

Image

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:

Image

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:

Image

É possível verificar o modo de seleção atual com o método getSelectionMode:

Image

O(s) elemento(s) selecionado(s) pode(m) ser obtido(s) por meio dos seguintes métodos:

Image

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:

Image

Já sabemos o suficiente para escrever o seguinte programa:

Image

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:

Image

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:

Image

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:

Image

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:

Image

5.2.5.5. componente JScrollBar

Vamos criar o seguinte aplicativo:

Image

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:

Image

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:

Image

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:

Image

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

Image

Veja, por exemplo, o resultado de RaisedBevel:

Image

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.

Image

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:

Image

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:

Image

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:

Image

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:

Image

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:

Image

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:

  1. MousePressed ao pressionar o botão
  2. MouseReleased ao soltá-lo
  3. 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:

Image

Vemos aqui os três eventos:

  1. MousePressed ao pressionar o botão inicialmente
  2. MouseDragged ao mover o mouse com o botão pressionado
  3. 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?

Image

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:

Image

Image

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.

Image

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

Image

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

Image

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.

Image

Em seguida, ao lado:

Image

Use a ferramenta 3 para indicar que B3 é um submenu aninhado.

À medida que o menu é projetado, a estrutura lógica da nossa janela evolui:

Image

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:

Image

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

Image

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

Image

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:

Image

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

Image

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:

Image

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:

Image

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.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:

Image

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:

      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

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:

Image

Exibição do console:

Chaîne saisie [dupont]

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:

Image

Os controles são os seguintes:

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:

Image

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

Image

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

Image

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:

     // adiciona-se o filtro *.txt
    jFileChooser1.addChoosableFileFilter(filtretxt);

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:

Image

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:

Image

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:

Image

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

Image

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:

Image

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

Image

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:

import com.lamatek.swingextras.*;

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:

Image

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:

Image

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
import com.lamatek.swingextras.*;

, perceberemos que o JBuilder nos fornece uma ajuda:

Image

O pacote com.lamatek foi encontrado.

  • Agora, no programa a seguir:
import com.lamatek.swingextras.*;

public class test{
  JFontChooser jFontChooser1=null;
}  

Ao digitar F1 na palavra-chave JFontChooser, obtém-se uma ajuda sobre essa classe:

Image

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:

Image

5.5. O aplicativo gráfico IMPOTS

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

Image

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:

Image

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:

Image

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:

    spinEnfants.setBounds(new Rectangle(137,60,40,27));
    contentPane.add(spinEnfants);

Antes de mais nada, o usuário deve utilizar a opção de menu Initialiser, que cria um objeto impots com o construtor

    public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception

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:

Image

  • 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:


public class application{
    
    public static main void(String arg[]){
        
    }
    
}// fim da classe

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:

  1. a classe application agora deriva da classe JApplet
  2. 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.

Image

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 cmd1To2_actionPerformed(ActionEvent e) {
..........
  }//transferência
  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:
public class interfaceAppli extends JApplet {
  • excluir a instrução que define o título da janela JFrame. Um applet JApplet não possui barra de título
    // this.setTitle("JList");
  • 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:

Image

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:

Image

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:

Image

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:

Image

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:

    DOS> java urlcontenu http://istia.univ-angers.fr/index.html

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:

Image

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:

Image

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>

Image

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

Image

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:

Image

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


    </applet>
  </body>
</html>

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:

    <param name="data" value="impots.txt">

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:

    urlDATA=getCodeBase()+"/"+nomFichier;

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:

Image

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

Image

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:

[tar xvzf jb4fndlinux_fr.tar.gz]
[tar xvzf jb4docs_fr.tar.gz]
[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:

[cd foundation]
[./fnd_linux_install.bin]

Aparece a primeira tela da instalação. Seguir-se-ão muitas outras:

Image

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

Image

Execute [suivant].

Image

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

Image

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

Image

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

Image

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

Image

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:

Image

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

Image

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

Image

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:

[./doc_install.bin]
Preparing to install...

Será realizada uma instalação gráfica:

Image

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

Image

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:

Image

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.

Image

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

Image

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].

Image

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

Image

A terceira tela solicita que você personalize seu projeto. Preencha e execute [Terminer].

Agora execute Fichier/Nouveau:

Image

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

Image

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]:

Image

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:

Image

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:

Image

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:

[ls -l *.java]
-rw-r--r--    1 root     root          135 mai  9 21:57 essai1.java
[/opt/jbuilder4/jdk1.3/bin/javac essai1.java]
[/opt/jbuilder4/jdk1.3/bin/java essai1]
coucou