GUI e componentes

Neste módulo veremos:

GUI e seus princípios

As GUI, do inglês, Graphical User Interfaces, são construídas a partir de componentes (também chamados de widgets) que interagem com o usuário via mouse, teclado ou outro dispositivo de entrada,

Na imagem abaixo podemos ver alguns dos principais componentes de uma janel gráfica, que são:

Java originalmente gerava as janelas gráficas através de um pacote chamado AWT, acrônimo de Another Window Toolkit. O pacote java.awt associa as capacidades gráficas aos recursos da plataforma local. Esta é uma característica interessante para algumas aplicações mas é limitante em outras pois impede uma padronização da interface a medida que gera componentes diferentes para cada plataforma.

Diferentemente do pacote java.awt os componentes do pacote javax.swing são escritos, manipulados e exibidos usando somente a tecnologia Java (não são sobrecarregados pelos recursos gráficos da plataforma) e por isso são também conhecidos como componentes puros, ou componenentes peso-leve.

Através dos componenentes da classe java.swing existe um controle total do comportamento e da aparência dos componentes gráficos.

Algumas das características do pacote Swing são:

Abaixo vemos a hierarquia de classes que definem os atributos e os comportamentos das classes de componentes gráficos. Cada classe é exibibida pelo nome de seu pacote e elas estão apresentadas hierarquicamente da classe raíz para as classes descendentes.

  java.lang.Object
      java.awt.Component
        java.awt.Container
          java.swing.JComponent

Logo, JComponent herda da classe Container que, por sua vez, herda da classe Component que herda da classe Object. Assim, todo JComponent é um Container que, por sua vez é um Component e assim por diante.

Um Component é um objeto que tem uma representação gráfica que pode ser mostrada na tela e oferece interação com o usuário. Exemplos deste componente são os botões, os checkboxes e as barras de rolagem (scrollbars).

Já o Container é uma coleção de componentes relacionados, ou mehor, é um componente que pode conter outros componentes. Fazem parte deste componente os painéis, os painéis com scroll e as windows.

As vedetes desta aula são os componentes derivados da subclasse JComponent.

Componentes gráficos

Uma GUI é formada por componentes.
Em Java temos os seguintes componentes mais comuns:

Veja todos os componentes Swing neste link.

Vejamos agora um exemplo e criação de um componente GUI aproveitado das páginas da Sun.

/** hello.java
 * @author java.sun.com
 */

import javax.swing.*;        

public class Hello {

    private static void criaMostraGUI() {
        //ajusta a decoracao da janela
        JFrame.setDefaultLookAndFeelDecorated(true);

        //cria uma noja janela
        JFrame frame = new JFrame("HelloWorld usando Swing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //adiciona label "Hello World" label.
        JLabel label = new JLabel("Hello World");
        frame.getContentPane().add(label);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //cria e mostra a plicacao usando thread
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                criaMostraGUI();
            }
        });
    }
}

Grande parte das aplicações envolvendo componentes GUI usam os eventos, as respostas as interações do usuário portato, é imperativo aprender sobre eventos para usar as componentes GUI.

Componentes e eventos

Os compoentes da GUI são baseados em eventos. Os eventos ocorrem quando há interação do usuário com a máquina, por exemplo, ao usar o teclado ou o mouse. Vários eventos podem ser disparados nestas situações. Veremos agora como programar os respostas da GUI aos eventos.

Existem vários tipos de eventos. Cada componente suporta vários tipos de eventos, como eventos de mouse, teclado, entre outros. São eventos comuns:

Cabe lembrar que os eventos aqui não estão organizados hierarquicamente em classes, como na realidade estão. Para uma descrição mais detalhada destas classes consulte as páginas de referência da API que está usando.

O mecanismo de evento tem três partes significativas e diferentes:

O processamento do evento é delegado ao ouvinte de eventos no aplicativo, ou melhor, quando ocorre um evento existe um mecanismo de aviso (dispatch) para os ouvintes daquele evento. Este dispatch é na realidade uma delegação para que o ouvinte cuide do tratamento de evento.

Para cada tipo de evento, ou melhor, objeto evento, existe uma interface ouvinte do evento correspondente. Esta interface é a encarregada deste tratamento.

Cada interface ouvinte especifica um ou mais métodos de tratamento do evento. Estes métodos devem ser declarados na classe que implementa a interface.

Observação

Lembre-se que uma interface é usada quando classes muito diferentes, ou melhor, pouco relacionadas, precisam compartilhar métodos e constantes comuns. Objetos que implementam a mesma interface podem responder às mesmas chamadas de métodos. Uma interface pode descrever genericamente funcionalidades e o programador pode depois implemetá-las para cada classe específica.

Cada tipo de evento tem uma ou mais interfaces ouvintes de eventos. São interfaces comuns:

Três situações devem ser observadas para o tratamentode eventos:

  1. Todo componente GUI deve registrar que haverá um evento associado a ele e que será motivo de programação específica;
  2. Sempre deverá ter um ouvinte (listener) que responderá a um evento;
  3. Cabe a interfece do ouvinte especificar um método de tratamento do evento;

Todo ouvinte tem uma lista de eventos aos quais deverá reagir. O programador deve registar o evento na lista dos eventos que o ouvinte deve reagir. O programador também deverá influir nos métodos de tratamento de eventos especificados pelas interfaces dos ouvintes.

Quando um evento ocorre, o componente GUI recebe da JVM um identificador (um número) que especifica o tipo de evento. Este ID é usado para decidir como será o dispatch, qual o método chamar para cada tipo de ouvinte. Por exemplo, para um ActionEvent o evento é despachado para o método actionPerformed.

Eventos em JTextField

Vejamos como isso ocorre no exemplo abaixo:

/** CampoTexto.java
 * @author EESR based on Deitel e Deitel
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CampoTexto extends JFrame {
  private JTextField texto1, texto2, texto3;

  // configura a GUI
  public CampoTexto()
  {
    super("Teste de JField");
    Container container = getContentPane();
    container.setLayout( new FlowLayout());

    texto1 = new JTextField(10); // dimensao do campo
    container.add(texto1);
    // texto default
    texto2 = new JTextField("Texto aqui"); 
    container.add(texto2);

    texto3 = new JTextField("Não permite edição", 30);
    texto3.setEditable(false);
    container.add(texto3);

    // registra tratadores de evento
    TratadorTexto tratat;
    tratat = new TratadorTexto();

    texto1.addActionListener(tratat);
    texto2.addActionListener(tratat);
    texto3.addActionListener(tratat);

    setSize(350,100);
    setVisible(true);
    }

    // executor do aplicativo
    public static void main (String args[]) {
	CampoTexto aplicacao = new CampoTexto();

	aplicacao.setDefaultCloseOperation(
	    JFrame.EXIT_ON_CLOSE);
    }

    // classe interna para tratar eventos
    private class TratadorTexto 
            implements ActionListener {

    public void actionPerformed (ActionEvent evento){
	String cadeia = "";

	// enter no texto1
	if (evento.getSource() == texto1)
	    cadeia = "texto1. evento: " + 
            evento.getActionCommand();
	// enter no texto2
	else if (evento.getSource() == texto2)
	    cadeia = "texto2. evento: " + 
            evento.getActionCommand();
	// enter no texto3
	else if (evento.getSource() == texto3)
	    cadeia = "texto3. evento: " + 
            evento.getActionCommand();
	JOptionPane.showMessageDialog(null, cadeia);
	}
    }
}

Detalhes:

Como dissemos, existem várias interfaces que respondem à varios eventos. Não veremos todas aqui mas algumas. Cabe ao programador sempre consultar a documentação para maiores detalhes.

Eventos em JButton

Veja abaixo um exemplo simples de uso de botões em Java

/** BotoesTexto.java
 * @author EESR
 */
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JOptionPane;

public class BotoesTexto extends JFrame {
  private JButton bot1;
  private JButton bot2;

  public BotoesTexto() {
    super ("Teste de botões com texto");
    Container cont = getContentPane();
    cont.setLayout (new FlowLayout());
    bot1 = new JButton("B1");
    cont.add(bot1);
    bot2 = new JButton("B2");
    cont.add(bot2);

    TrataBotoes handler = new TrataBotoes();
    bot1.addActionListener (handler);
    bot2.addActionListener (handler);
  }

  public static void main (String args[])
  {
    BotoesTexto bt = new BotoesTexto();
    bt.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    bt.setSize(200,100);
    bt.setVisible(true);
  }

  private class TrataBotoes implements ActionListener
  {
    public void actionPerformed (ActionEvent evento)
    {
      if (evento.getSource()==bot1)
	JOptionPane.showMessageDialog (BotoesTexto.this, 
	"Botão 1");
      else
        JOptionPane.showMessageDialog (BotoesTexto.this, 
	  "Botão 2");
    }
  }// private
}

Note que, como para JTextField os JButton geram ActionEvent que podem ser processados por qualquer objeto ActionListener (que é na verdade uma interface). É o método da interface ActionPerformed() que recebe um ActionEvent.

Veja agora a segunda versão deste mesmo programa que trata botões e um campo de texto. É uma boa dica para a sua calculadora.

/** BotoesTexto.java
 * @author EESR
 * @version 0.2
 */
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JOptionPane;

public class BotoesTexto extends JFrame {
  private JButton bot1;
  private JButton bot2;
  private JTextField texto;

  public BotoesTexto() {
    super ("Teste de botões com texto");
    Container cont = getContentPane();
    cont.setLayout (new FlowLayout());

    texto = new JTextField(20);
    cont.add(texto);
    bot1 = new JButton("B1");
    cont.add(bot1);
    bot2 = new JButton("B2");
    cont.add(bot2);

    TrataBotoes handler = new TrataBotoes();
    bot1.addActionListener (handler);
    bot2.addActionListener (handler);
  }

  public static void main (String args[])
  {
    BotoesTexto bt = new BotoesTexto();
    bt.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    bt.setSize(250,100);
    bt.setVisible(true);
  }

  private class TrataBotoes implements ActionListener
  {
    public void actionPerformed (ActionEvent evento)
    {
      if (evento.getSource()==bot2) {
        int num = Integer.parseInt (texto.getText());
	num++;
	JOptionPane.showMessageDialog(null, 
          "Um a mais é: " + num);
      }
      else
	texto.setText("1234");
    }
  }// private
}

Procura na API correspondente, para cada componente GUI, no pacote java.awt principalmente, a quais tipos de objetos o dado componente reage, quais são os eventos gerados e os métodos a serem programados.

Última modificação feita em: 18 de setembro de 2006
Evandro Eduardo Seron Ruiz, PhD (evandro at usp ponto br)
www.imagcom.org/evandro/ibm1030