Tutorial Java - Swing Básico

Introdução

    Na era da Web, quase passa desapercebido a importância das aplicações Desktop e sua enorme variedade de aplicativos para diversos sistemas operacionais. O desafio e construir aplicações Desktop que possam ser executadas nestes diversos sistemas operacionais, sem que tenhamos que reescrever o sistema. 

    No Portal Java(http://www.portaljava.com), em pesquisa on-line aparece um resultado que sinaliza a importância as aplicações Desktop.

Portal Java

    Neste tutorial vamos introduzir os conceitos de Java Swing, que constitui um importante conjunto de API's para construção de robustas Interfaces Gráficas com o  Usuários.

JFC e Swing

    Quando a linguagem Java 1.0 foi lançada, ela continha uma biblioteca de classes que a SUN chamou de  AWT(Abstract Window Tool-kit – ferramentas de janela abstratas) para programação GUI básica.
    A Netscape em 1996 criou uma biblioteca GUI chamada de IFC-Internet Foudation Classes. A SUN trabalhou junto com a Netscape para aperfeiçoar e criou uma biblioteca de interface de usuário com o nome código de “Swing”, que alguns chamaram de “conjunto Swing”.
    JFC é abreviatura de Java Foundation Classes, que abrangem um grupo das características para construir Interfaces Gráficas com o Usuários (GUIs) e adição de ricas funcionalidades  e interatividade com aplicações Java.
    Swing é um kit de ferramentas GUI e faz parte da JFC.
    Swing não é um substituto completo do AWT, simplesmente fornece à interface de usuário componentes mais capazes

Galeria de componentes Swing:

JApplet JApplet
Borders Borders
JButton JButton
JCheckBox JCheckBox
JCheckBoxMenuItem JCheckBoxMenuItem
JColorChooser JColorChooser
JComboBox JComboBox
ImageIcon ImageIcon
JDialog JDialog
JFileChooser JFileChooser
JInternalFrame JInternalFrame
JLabel JLabel
JList JList
JMenu JMenu
JMenuBar JMenuBar
JOptionPane JOptionPane
JPopupMenu JPopupMenu
JRadioButton JRadioButton
JRadioButtonMenuItem JRadioButtonMenuItem
JScrollBar JScrollBar
JScrollPane JScrollPane
JSlider JSlider
JSplitPane JSplitPane
JTabbedPane JTabbedPane
JTable JTable
JTextArea JTextArea
JTextField JTextField
JToggleButton JToggleButton
JToolBar JToolBar
JToolTip JToolTip
JTree JTree

API Swing

    A API Swing é poderosa, flexível e imensa, que possui pacotes públicos, cada um com sua própria finalidade distinta:

    javax.swing

    Pacote swing de alto nível, consiste primariamente de componentes, adaptadores, modelos padrão de componentes e interface.

    javax.swing.border
   
    O pacote border declara a interface Border e classes,  que define especifico estilo de borda.

    javax.swing.colorchooser

    O pacote colorchooser contem suporte de para classes para componentes  color chooser .

    javax.swing.event
   
    O pacote de event é para eventos e listeners específicos Swing. Adiciona ao  java.awt.event types, componentes Swing podem gerar seus próprios tipos de eventos.

    javax.swing.filechooser
   
    O pacote filechooser contem classes de suporte para componentes de seleção de arquivos.

    javax.swing.plaf
    

    Plug-in look-and-feel (PLAF) pacote que contém Interfaces com usuário(UI) classes (delegadas) que implementam diferentes look-and-feel aspects para componentes Swing. Há também alguns pacotes de PLAF sob a hierarquia. 

    javax.swing.table
   
    O pacote table contem suporte para interfaces e e classes para o componente Swing table.

    javax.swing.text

    O pacote text contem classes de suporte para o framework do Swing de documento.

    javax.swing.text.html

    O pacote text.html contem classes de suporte para HTML versão  3.2 interpretador e analisador.

    javax.swing.text.rtf

    O pacote text.rtf contem classes de suporte para um básico interpretados  Rich Text Format (RTF).

    javax.swing.tree

    O pacote tree contem interface e classes para o componente tree do Swing.

    javax.swing.undo

    O pacote undo provê classes de suporte para implementar a capacidade de fazer/desfazer nos GUI.

    javax.accessibility

    O pacote de acessibilidade da JFC é incluido nas classes Swing. Entretanto, seu uso não será discutido aqui.

Componentes Swing

    O widget é um termo sem tradução que designa componentes de interface gráfica com o usuário (GUI). Qualquer item de uma interface gráfica é chamada de widget, por exemplo: janelas, botões, menus ítens de menus, ícones, barras de rolagem, etc.

    O pacote de acessibilidade da JFC é incluído nas classes Swing. Entretanto, seu uso não será discutido aqui.

CompTree
Hierarquia de componentes similares ao AWT

CompTree
Hierarquia de componentes novos no Swing

Usando componentes Swing na construção de interfaces com o usuário.

    O exemplo AloMundo Swing, foi criado uma interface com o usuário usando componentes do pacote javax.swing.

Código:

import javax.swing.*; 


public class AloMundoSwing {
/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void criaExibeGUI() {
//Faz com que tenha uma decoracao de janela
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria e organiza a janela
JFrame frame = new JFrame("AloMundoSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Adiciona o rotulo "Alo Mundo".
JLabel label = new JLabel("Alo Mundo");
frame.getContentPane().add(label);

//Exibe a janela
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
criaExibeGUI();
}
});
}
}

Resultado:

AloMundoSwing

Este é um simple exemplos de aplicação Swing que pode ser escrito. No código do programa Swing temos:

   1. Importar os pacotes pertinentes:
   2. Posicionando o container top-level.
   3. Exibição do container.
   4. Thread-safe. 

    import java.awt.*;
    import java.awt.event.*;

    Estes dois pacotes são requeridos por que os componentes Swing usam a infra-estrutura AWT, incluindo o modelo de eventos. O modelo de eventos governa como um componente reage a um evento semelhante a um clique de botão ou o movimento de mouse.
    Para fazer o programa fechar, quando o botão Close [x] é clicado, incluímos o código:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    O exemplo AloMundoSwing tem um único container  top-level, um JFrame. Implementando uma instância da classe Jframe, um frame é uma janela, por padrão, tem ornamentos semelhantes a bordas, títulos, botões com ícones para fechar a janela. Aplicações tipicamente GUI usam um frame no mínimo.
    O código a seguir, mostra como um frame é construído e exibido:

JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("HelloWorldSwing");
...
frame.pack();
frame.setVisible(true);

    A exceção dos containes top-level, semelhantes a um Jframe, todos os componentes descendentes da classe JComponent. HelloWorldSwing usa um  JComponent descendente chamado JLabel, que exibe um texto Hello World. As duas próximas linhas de código, constrói e adiciona um componente JLabel num frame:

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

    Pode parecer estranho, mas é recomendado utilizar o código a seguir para que as aplicações GUI não tenham problemas de threas-safety que podem parar a interface antes de aparecer a exibição.

javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        /* cria e exibe o GUI */
    }
});

Look e Feel

    Swing permite que seja especificado um look and feel para os usuários do programas--Java, GTK+, Windows, e assim por diante.

Código

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

public class AplicacaoSwing implements ActionListener {
private static String labelPrefix = "Numero de cliques de botao: ";
private int numClicks = 0;
final JLabel label = new JLabel(labelPrefix + "0 ");

//Especifica o look and feel para usar. Valores validos:
//null (usa o padrao), "Metal", "System", "Motif", "GTK+"
final static String LOOKANDFEEL = "System";

public Component createComponents() {
JButton button = new JButton("Eu sou um botao Swing!");
button.setMnemonic(KeyEvent.VK_I);
button.addActionListener(this);
label.setLabelFor(button);

/*
* Um facil caminho para colocar um espaco entre o container top-level
* que contem e para colocar JPanel contido
* tem uma borda vazia (empty).
*/
JPanel pane = new JPanel(new GridLayout(0, 1));
pane.add(button);
pane.add(label);
pane.setBorder(BorderFactory.createEmptyBorder(
30, //top
30, //left
10, //bottom
30) //right
);

return pane;
}

public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText(labelPrefix + numClicks);
}

private static void initLookAndFeel() {
String lookAndFeel = null;

if (LOOKANDFEEL != null) {
if (LOOKANDFEEL.equals("Metal")) {
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
} else if (LOOKANDFEEL.equals("System")) {
lookAndFeel = UIManager.getSystemLookAndFeelClassName();
} else if (LOOKANDFEEL.equals("Motif")) {
lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
} else if (LOOKANDFEEL.equals("GTK+")) { //novo a partir da versao 1.4.2
lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
} else {
System.err.println("Valor inesperado de especifico LOOKANDFEEL: "
+ LOOKANDFEEL);
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
}

try {
UIManager.setLookAndFeel(lookAndFeel);
} catch (ClassNotFoundException e) {
System.err.println("Nao pode encontrar classe especifica para o look and feel:"
+ lookAndFeel);
System.err.println("Voce incluiu a biblioteca L&F library no class path?");
System.err.println("Usa o padrao look and feel.");
} catch (UnsupportedLookAndFeelException e) {
System.err.println("Nao pode ser especificado um look and feel ("
+ lookAndFeel
+ ") nesta plataforma.");
System.err.println("Uso do padrao look and feel.");
} catch (Exception e) {
System.err.println("Nao pode obter especifico look and feel ("
+ lookAndFeel
+ "), por alguma razao .");
System.err.println("Uso do padrao look and feel.");
e.printStackTrace();
}
}
}

/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void criaExibeGUI() {
//Inicializa o look and feel.
initLookAndFeel();

//Faz com se tenha janelas com decoracoes agradaveis.
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria e organiza janela.
JFrame frame = new JFrame("AplicacaoSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

AplicacaoSwing app = new AplicacaoSwing();
Component contents = app.createComponents();
frame.getContentPane().add(contents, BorderLayout.CENTER);

//Exibe a janela.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
criaExibeGUI();
}
});
}
}

Resultado:


AplicacaoSwing AplicacaoSwing

    A parte de código a seguir,  mostra como AplicacaoSwing especifica de que maneira deve ser usado o  Java look and feel:

String lookAndFeel = null;
...
lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
...
try {
    UIManager.setLookAndFeel(lookAndFeel);
} catch (Exception e) { }
...// Cria e exibe um GUI...

Construção de Botões e Rótulos.

    Como a maioria dos GUIs, a AplicacaoSwing GUI contem um botão e um  rótulo(label). O código a seguir, inicializa o botão:
    JButton button = new Jbutton("Eu sou um botao Swing!");
    button.setMnemonic('i');
    button.addActionListener(/*...cria um action listener...*/);

    A primeira linha cria o botão. A segunda marca a letra "i" um mnemônico para o usuário poder usar e simular um clique do botão. Por exemplo, no Java  look and feel, tipicamente é a tecla “Alt-i” que faz isto. A terceira linha registra para fornecer o evento (event handler) para o clique do botão.

    Onde as variáveis são declaradas e inicializadas os rotulos.

    private static String labelPrefix = "Numero de cliques de botao: ";
    private int numClicks = 0;   
   
    Código de inicialização do GUI
    final JLabel label = new JLabel(labelPrefix + "0    ");
   
    label.setLabelFor(button);
   
    label.setText(labelPrefix + numClicks);

Adicionando um Componente ao Container

    O programa AplicacaoSwing, agrupa o label e o botão no container (um JPanel) antes de adicionar o componente no frame. A seguir o código de inicialização do container:

Código:

Resultado:

    A primeira linha cria um container e atribui um gerenciador de layout- no objeto determina o tamanho e posição de cada componente e adiciona para o container. O código new GridLayout(0,1) cria um gerenciador de layout que força o conteúdo do container's ser exibido numa unica coluna, com cada componente que tem o mesmo tamanho. 

            JPanel pane = new JPanel(new GridLayout(0, 1));

              pane.add(button);
             pane.add(label);
             pane.setBorder(BorderFactory.createEmptyBorder(...);
    

    Nestas duas linhas adiciona o botão e label no container. A última linha adiciona uma borda.
    Para adição de bordas ao painel, o código cria e ajusta uma borda que forneça algum espaço vazio em torno do container - 30 pixels extras no top,  e 10 pixels extras a esquerda( left), direita(right) no rodapé (bottom).

Adicionando bordas ao Redor dos Componentes

Código:

Resultado:

AplicacaoSwing

        pane.setBorder(BorderFactory.createEmptyBorder(
        30, //top
        30, //left
        10, //bottom
        30) //right);
   
    O código adiciona uma borda.
    Para adição de bordas ao painel, o código cria e ajusta uma borda que forneça algum espaço vazio em torno do container - 30 pixels extras no top,  e 10 pixels extras a esquerda( left), direita(right) no rodapé (bottom).
    Bordas tem características herdadas do  JPanel da classe  Jcomponent. Um objeto Border não é um JComponent; isto é, usa um ou mais  JComponents para pintar o componente borda.   

Handling Events

    Cada vez que o usuário digita um caráter ou aperta um botão do mouse, um evento ocorre. Todo o objeto pode ser notificado do evento.  Todo o objeto tem que implementar apropriadamente a interface e registra um event listener  na apropriada fonte do evento.
    A classe AplicacaoSwing implementa um event handler para o clique do botão(action events). Observe o código a seguir:

    public class AplicacaoSwing implements ActionListener {
        ...
            JButton button = new Jbutton("Eu sou um botao Swing!");
            button.addActionListener(this);
        ....

        public void actionPerformed(ActionEvent e) {
            numClicks++;
            label.setText(labelPrefix + numClicks);
       }
    } 

    Cada event handler requer três partes no código:

   1. Na declaração para a classe event handler, uma linha de código especifica na classe a implementação da interface  listener ou extende a classe que implementa a interface listener. Por exemplo:

          public class MinhaClasse implements ActionListener {   

Handling

    Em geral, para detectar os cliques do botão do usuário na tela(ou equivalente no teclado), um programa tem que ter um objeto que implemente a interface ActionListener . O programa pode registrar que o objeto no action listener no botão (a fonte do evento), usa o método addActionListener. Onde o usuário clicar com botão na tela que dispara o evento.
    Este resultado na invocação do action listener's do método actionPerformed(o único método na interface ctionListener). O simples argumento para o método  no objeto ActionEvent que dá sobre o evento e na fonte do evento.

    Os componentes Swing podem gerar muitos tipos de eventos.

    Alguns eventos e suas associado no Event Listeners:

Ação do resultado do evento Tipo Listener
Clique do usuário no botão,  pressiona Enter quando um campo de texto, ou item menu de seleção ActionListener
Usuário fecha um frame(janela principal) WindowListener
Usuário preciona um botão do mouse quando o cursor passa sobre um componente MouseListener
Usuário move o mouse sobre um componente. MouseMotionListener
O componente torna-se visível ComponentListener
O componente recebe o foco do teclado FocusListener
Mudança de seleção na tabela ou lista ListSelectionListener
Variação de uma propriedade no componente semelhante a um texto no label. PropertyChangeListener

Conversor de temperatura

    Esta é uma simples ferramenta de conversão. O usuário entre com uma dad temperatura em graus Celsius e clica no botão Converter. Um label exibe a temperatura equivalente e graus Fahrenheit.

Código:

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

public class ConversaoCelsius implements ActionListener {
JFrame converterFrame;
JPanel converterPanel;
JTextField tempCelsius;
JLabel celsiusLabel, fahrenheitLabel;
JButton convertTemp;

public ConversaoCelsius() {
//Cria e organiza janela.
converterFrame = new JFrame("Converte graus Celsius para Fahrenheit");
converterFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
converterFrame.setSize(new Dimension(120, 40));

//Cria e constroi o painel.
converterPanel = new JPanel(new GridLayout(2, 2));

//Adiciona o widgets.
adicionaWidgets();

//Marca padrao o o botao
converterFrame.getRootPane().setDefaultButton(convertTemp);

//Adiciona o painel na janela
converterFrame.getContentPane().add(converterPanel, BorderLayout.CENTER);

//Exibe a janela.
converterFrame.pack();
converterFrame.setVisible(true);
}

/**
* Cria e adciona o widgets.
*/
private void adicionaWidgets() {
//Cria widgets.
tempCelsius = new JTextField(2);
celsiusLabel = new JLabel("Graus Celsius", SwingConstants.LEFT);
convertTemp = new JButton("Converte");
fahrenheitLabel = new JLabel("Graus Fahrenheit", SwingConstants.LEFT);

//Listen para evento do botao Converte
convertTemp.addActionListener(this);

//Adiciona widgets para container.
converterPanel.add(tempCelsius);
converterPanel.add(celsiusLabel);
converterPanel.add(convertTemp);
converterPanel.add(fahrenheitLabel);

celsiusLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
fahrenheitLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
}

public void actionPerformed(ActionEvent event) {
//Parse degrees Celsius as a double and convert to Fahrenheit.
int tempFahr = (int)((Double.parseDouble(tempCelsius.getText()))
* 1.8 + 32);
fahrenheitLabel.setText(tempFahr + " Graus Fahrenheit");
}

/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void criaExibeGUI() {
//Faz com se tenha janelas com decoracoes agradaveis.
JFrame.setDefaultLookAndFeelDecorated(true);

ConversaoCelsius converter = new ConversaoCelsius();
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
criaExibeGUI();
}
});
}
}

Resultado:

ConversaoGraus

    Vamos examinar o código para ver como  ConversaoCelsius analisa o número que entrou no JTextField.
    Primeirot, este código constroe um JTextField:

    JTextField tempCelsius = null;
    ...
    tempCelsius = new JtextField(5);
   
    O argumento inteiro que é passado no construtuor do JTextField --5 no exemplo—indica o numero de colunasno campo. Este número é usado junto com o metrics fornecido pela pela fonte para calcular a largura preferida do campo, que é usada por layout managers. Este número não limita o número de caracteres que o usuário pode entrar.

    Nós queremos executar a conversão quando o usuário clicar um botão ou pressionar ENTER no campo do texto.  Para fazer assim, nós adicionamos um action event ao campo para o botão convertTemp e do texto tempCelsius.

    convertTemp.addActionListener(this);
    tempCelsius.addActionListener(this);
    ...
    public void actionPerformed(ActionEvent event) {
            //Analisa graus Celsius para um double e converte para Fahrenheit.
            int tempFahr = (int)((Double.parseDouble(tempCelsius.getText()))
                         * 1.8 + 32);
            fahrenheitLabel.setText(tempFahr + " Fahrenheit");
    }

    O código event-handling entra no método actionPerformed. Chama o método do getText no campo do texto, tempCelsius, para recuperar os dados dentro dele. Em seguida usa o método parseDouble para analisar/converter o texto para um número de ponto flutuante e precisão dupla antes de converter a temperatura e transformar num resultado inteiro. Finalmente, chama o método do setText no fahrenheitLabel para fazer um label indicar a temperatura convertida.

Gerenciadores de Layout

FlowLayout

    O gerenciador de layout de “fluxo” apenas posiciona os componentes em fila, um após o outro, cada qual com suas dimensões mínimas. O FlowLayout imita o fluxo de textos, e pode alinhar os componentes à direita, à esquerda, ou centraliza-los dentro do container. O uso mais comum deste layout é para preencher uma linha com maior quantidade possível de componentes, por exemplo em barras de ferramentas ou de status.

BorderLayout

    BorderLayoutO BorderLayout posiciona os componentes nas “bordas” do container, deixando a maior parte de sua área disponível para o componente inserido no centro. Cada borda é identificado por um ponto cardeal(NORTH,SOUTH, EAST, WEST). Apenas um componente será visível em cada borda, expandindo-se na altura ou largura para ocupar toda a borda do container, porém assumindo o valor mínimo na outra dimensão.
    Note que esta disposição reflete o padrão na maioria das aplicações desktop, como processadores de texto ou programas de desenho: uma barra de ferramentas ao norte, uma barra de status ao sul, opcionalmente outras barras de ferramentas ao leste e oeste, e uma área de edição ao centro.

Demo BorderLayout


Código:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class DemoBorderLayout {
public static boolean RIGHT_TO_LEFT = false;

public static void addComponentsToPane(Container pane) {
if (!(pane.getLayout() instanceof BorderLayout)) {
pane.add(new JLabel("O Container não usa BorderLayout!"));
return;
}

if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(
java.awt.ComponentOrientation.RIGHT_TO_LEFT);
}

JButton button = new JButton("Boatao 1 (PAGINA_INICIAR)");
pane.add(button, BorderLayout.PAGE_START);

//Faz a centralização de um grande componente, deste que
//tipico do uso de BorderLayout.
button = new JButton("Boatao 2 (CENTRO)");
button.setPreferredSize(new Dimension(200, 100));
pane.add(button, BorderLayout.CENTER);

button = new JButton("Boatao 3 (INICIAR_LINHA)");
pane.add(button, BorderLayout.LINE_START);

button = new JButton("NOME-LONGO Boatao 4 (FIM_PAGINA)");
pane.add(button, BorderLayout.PAGE_END);

button = new JButton("5 (FIM_LINHA)");
pane.add(button, BorderLayout.LINE_END);
}
/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void createAndShowGUI() {
//Faz com que tenha uma decoracao de janela.
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria e organiza a janela.
JFrame frame = new JFrame("DemoBorderLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Organiza o conteudo no painel.
addComponentsToPane(frame.getContentPane());
//Uso do conteudo do painel por padrão o BorderLayout. No need for
//setLayout(new BorderLayout());

//Exibe janela.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Resultado:

DemoBorderLayout

GridLayout

    O GridLayout organiza os componentes em uma “grade” ou tabela com número de linhas e colunas pré-fixado no momento da sua criação. Todas as células possuem o mesmo tamanho, e são expandidas igualmente para ocupar a área total disponível no container. Caso haja menos componentes do que células, o espaço das células vázias é distribuído entre os componentes; mas podem ficar células vázias nas últimas colunas da última linha.
    O GridLayout é adequado quando se deseja que um grupo de componentes (ex.? Um grupo de botões) tenha dimensões uniformes, como na caixa de ferramentas de um programa de desenho ou par de botões “OK” e “Cancelar” de um diálogo.

Demo GridLayout

Código:

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

public class DemoGridLayout {
public final static boolean RIGHT_TO_LEFT = false;

public static void addComponentsToPane(Container pane) {
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(
ComponentOrientation.RIGHT_TO_LEFT);
}

pane.setLayout(new GridLayout(0,2));

pane.add(new JButton("Botoao 1"));
pane.add(new JButton("Botoao 2"));
pane.add(new JButton("Botoao 3"));
pane.add(new JButton("Botao Nome-Longo 4"));
pane.add(new JButton("5"));
}

/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void createAndShowGUI() {
//Faz com que tenha uma decoracao de janela.
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria e organiza a janela.
JFrame frame = new JFrame("DemoGridLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Organiza o conteudo no painel.
addComponentsToPane(frame.getContentPane());

//Exibe janela.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}


Resultado:

DemoGridLayout

GridBagLayout

    Com nome estranho(“saco de grades”), o GridBagLayout é o mais poderoso e o mais flexível dos gerenciadores fornecidos com o J2EE. Ele imita em linhas gerais o funcionamento de uma tabela HTML, em que um componente pode ocupar várias células, ou seja, se estender por várias colunas e linhas.
    Os componentes podem ser expandidos para ocupar toda a área das suas células, ou serem alinhados em qualquer posição do conjunto de células. Linhas e colunas assumem as dimensões do maior componente, mas é necessário que tenham todas o mesmo tamanho. E algumas células podem ser configuradas para ocuparem toda a área disponível no container.

    Este layout tem como base a utilização de um GridBagConstraints para cada componente inserido. É este objeto que proporcionará a liberdade que queremos com o layout. A GridBagConstraints é uma classe que não possui métodos, ela servirá simplesmente para armazenar as informações para cada componente adicionado. Vamos dar uma olhada nas propriedades da classe:

anchor: Essa propriedade é utilizada somente quando o tamanho do componente é menor que a área que lhe foi concedida. Normalmente, queremos que nosso componente ocupe toda a área disponível, mas em casos especiais, não podemos redimensionar os componentes. Sendo assim, o layout precisa saber em que posição da célula deixará o componente. Os valores para esse campo são de dois tipos: Absolutos (CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, e NORTHWEST) e Relativos (PAGE_START, PAGE_END, LINE_START, LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START and LAST_LINE_END). O valor padrão é CENTER.

fill: Determina como redimensionar o componente. Valores possíveis para esta propriedade são:
NONE: Não redimensiona o componente
HORIZONTAL: Redimensiona horizontalmente, fazendo com que o mesmo ocupe toda a área horizontal na célula
VERTICAL: Redimensiona verticalmente, fazendo com que o mesmo ocupe toda a área vertical na célula
BOTH: Redimensiona para ambas as direções.
Valor padrão é NONE

gridx e gridy

    Especificam a posição X,Y para adicionar o componente. Não é necessário alterar seus valores, pois seu valor padrão é a constante RELATIVE e portanto o layout adicionará após o último componente que foi colocado.
- gridx: Permite especificar qual a posição absoluta horizontalmente que o componente será adicionado.
- gridy: Permite especificar qual a posição absoluta verticalmente que o componente será adicionado.

gridheight e gridwidth 

    Especificam o tamanho do componente baseado em células. É com essa propriedade que você indicará que um componente seu ocupará duas células, ou ocupurá tantas quanto forem necessárias para ir até o final da tela. Lembrem-se é células e não pixels
    Nestes valores podem ser utilizadas duas constantes: REMAINDER e RELATIVE. REMAINER fará com que o componente se estique até a última célula. Já o RELATIVE fará com que o componente ocupe todas as casas com excessão da última.
- gridheight: Especifica o número de células que o componente ocupará verticalmente. Valor padrão é 1.
- gridwidth: Especifica o número de células que o componente ocupará horizontalmente. Valor padrão é 1.

insets

    Indica as distãncias entre os componentes do layout. Um Insets possui valores para as 4 direções, cima, baixo, direita e esquerda. Permitindo com isso muita flexibilidade no gerenciador. Valor padrão é new Insets(0, 0, 0, 0)

weight

    Essas propriedades especificam um percentual de crescimento da célula, não do componente, quando a mesma precisa ser redimensionada. É dito isso, pois se o componente não pode se redimensionar, pois a propriedade fill do constraint afirma isso, o componente não vai sofrer as alterações, mas a célula irá aumentar.
Com este layout é possível informar que uma célula redimensionará 75% e o outra 25%, portanto o primeiro componente receberá 3 vezes mais tamanho do que o segundo.

    O valor padrão é 0 e os valores percentuais são dados em casas decimais, por exemplo: 0.03 é igual a 3%, 1.00 é igual a 100% e por aí vai.
- weightx: Peso em x. Especifica um peso no redimensionamento. Este peso será utilizado para um cálculo que o layout faz para determinar quais as células irão redimensionar horizontalmente, quais não irão, e quais aumentarão mais que os outros.
- weighty: Peso em y. Especifica um peso no redimensionamento. Este peso será utilizado para um cálculo que o layout faz para determinar quais as células irão redimensionar verticalmente, quais não irão, e quais aumentarão mais que os outros. 

ipadx e ipady 

    Determina um adicional nas bordas internas do componenete. Essa propriedade modifica o tamanho mínimo de cada componente. O tamanho mínimo será o ipad + o valor mínimo do componente.
- ipadx: Valor para ser adicionado horizontalmente.
- ipady: Valor para ser adicionado verticalmente.

    Podemos afirmar com segurança que qualquer disposição de componentes pode ser configurada em um GridBagLayout. Por outro lado, a quantidade de constraints(propriedades e restrições de layout) possível para cada componente também deu a este gerenciador a fama de ser difícil de programar.

Demo GridBagLayout

Código:

import java.awt.*;
import javax.swing.JButton;
import javax.swing.JFrame;

public class DemoGridBagLayout {
final static boolean shouldFill = true;
final static boolean shouldWeightX = true;
final static boolean RIGHT_TO_LEFT = false;

public static void addComponentsToPane(Container pane) {
if (RIGHT_TO_LEFT) {
pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}

JButton button;
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
//altura natural, largura maxima.
c.fill = GridBagConstraints.HORIZONTAL;
}

button = new JButton("Botao 1");
if (shouldWeightX) {
c.weightx = 0.5;
}
c.gridx = 0;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Botao 2");
c.gridx = 1;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Botao 3");
c.gridx = 2;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Botao 4 - Nome-Longo");
c.ipady = 40; //faz o componente no alto.
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 1;

pane.add(button, c);

button = new JButton("5");
c.ipady = 0; //esvazia por padrao
c.weighty = 1.0; //requisita um espaco vertical extra.
c.anchor = GridBagConstraints.PAGE_END; //espaco em baixo.
c.insets = new Insets(10,0,0,0); //top padding
c.gridx = 1; //alinhamento do botao 2.
c.gridwidth = 2; //2 colunas largas.
c.gridy = 2; //terceira linha.
pane.add(button, c);
}

/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void createAndShowGUI() {
//Faz com que tenha uma decoracao de janela.
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria e organiza a janela.
JFrame frame = new JFrame("DemoGridBagLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Organiza o conteudo no painel.
addComponentsToPane(frame.getContentPane());

//Exibe janela.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Resultado:

DemoGridBagLayout

NullLayout

    Na verdade o Null Layout não é um gerenciador de layout, mas sim a ausência de qualquer gerenciador (equivalente a definir a propriedade layout do container com o valor null). O resultado é que , no IDE, componentes podem ser posicionados à vontade na área de desenho; eles permanerão na posição onde foram colocados e com as dimensões indicadas pelo desenvolvedor.

AbsoluteLayout

    O AbsoluteLayout não é um gerenciador padrão do Java, mas uma adição do NetBeans; seu uso requer que o pacote modules/ext/AbsoluteLayout.jar seja copiado para a estação do usuário e configurado no classpath. Ele funciona como um Null Layout, co a diferença de que as dimensões do container são calculadas corretamente, permitindo o uso do método pack() (com o Null Layout, o resultado são dimensões [0,]). Porém, AbsoluteLayout apresenta todas as desvantagens do Null Layout, portanto também, não é recomendado para uso geral.

Demo Swing Fases da Lua

OBS: É necessário que os arquivos *.gif estejam no mesmo diretório do arquivo fonte FasesDaLua.java.

Transfira para seu computador o Arquivo_fotos.zip que contem os arquivos *.gif.

Código:

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

public class FasesDaLua implements ActionListener {
final static int NUM_IMAGES = 8;
final static int START_INDEX = 3;

ImageIcon[] images = new ImageIcon[NUM_IMAGES];
JPanel mainPanel, selectPanel, displayPanel;

JComboBox phaseChoices = null;
JLabel phaseIconLabel = null;

public FasesDaLua() {
//Cria a selecao das faaes e exibe no painel.
selectPanel = new JPanel();
displayPanel = new JPanel();

//Adiciona varios widgets para o sub-painel.
addWidgets();

//Cria um painel contendo dois sub-paineis.
mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

//Adiciona e seleciona painel de exibicao para o painel principal.
mainPanel.add(selectPanel);
mainPanel.add(displayPanel);
}

/*
* Obtem a imagem e organiza o widgets.
*/
private void addWidgets() {
//Obtem a imagem e coloca no array de ImageIcons.
for (int i = 0; i < NUM_IMAGES; i++) {
images[i] = createImageIcon("image" + i + ".jpg");
}

/*
* Cria um rotulo para exibir as imagens das fases da lua e
* coloca uma bordar ao redor desta.
*/
phaseIconLabel = new JLabel();
phaseIconLabel.setHorizontalAlignment(JLabel.CENTER);
phaseIconLabel.setVerticalAlignment(JLabel.CENTER);
phaseIconLabel.setVerticalTextPosition(JLabel.CENTER);
phaseIconLabel.setHorizontalTextPosition(JLabel.CENTER);
phaseIconLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLoweredBevelBorder(),
BorderFactory.createEmptyBorder(5,5,5,5)));

phaseIconLabel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(0,0,10,0),
phaseIconLabel.getBorder()));

//Cria um combo box com cada selecao da fase lunar.
String[] phases = { "Nova", "Maximo Crescente", "Primeiro Quarto",
"Waxing Gibbous", "Cheia", "Waning Gibbous",
"Terceiro Quarto", "Crescente" };
phaseChoices = new JComboBox(phases);
phaseChoices.setSelectedIndex(START_INDEX);

//Exibe a primeira imagem.
phaseIconLabel.setIcon(images[START_INDEX]);
phaseIconLabel.setText("");

//Adiciona uma borda em volta do painel de selecao.
selectPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Selecione uma Fase"),
BorderFactory.createEmptyBorder(5,5,5,5)));

//Adiciona borda em vola do painel de exibicao.
displayPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Exibe Fases"),
BorderFactory.createEmptyBorder(5,5,5,5)));

//Adiciona fases da lua no combo box para selecionar imagem no painel e rotulo da imagem.
displayPanel.add(phaseIconLabel);
selectPanel.add(phaseChoices);

//Listen para o events do combo box.
phaseChoices.addActionListener(this);
}

public void actionPerformed(ActionEvent event) {
if ("comboBoxChanged".equals(event.getActionCommand())) {
//Update the icon to display the new phase.
phaseIconLabel.setIcon(images[phaseChoices.getSelectedIndex()]);
}
}

/** Retorna um ImageIcon, ou null se o path for invalido. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imageURL = FasesDaLua.class.getResource(path);

if (imageURL == null) {
System.err.println("Caminho nao encontrado: "
+ path);
return null;
} else {
return new ImageIcon(imageURL);
}
}

/**
* Cria um GUI e o exibe. Para thread safety,
* este metodo podera invocar para uma thread
* de disparo de evento(event-dispatching thread).
*/
private static void criaExibeGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);

//Cria uma nova instancia de FasesDaLua.
FasesDaLua phases = new FasesDaLua();

//Cria e organiza a janela.
JFrame lunarPhasesFrame = new JFrame("Fases da Lua");
lunarPhasesFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
lunarPhasesFrame.setContentPane(phases.mainPanel);

//Exibe janela.
lunarPhasesFrame.pack();
lunarPhasesFrame.setVisible(true);
}
public static void main(String[] args) {
//Agenda um trabalho para o event-dispatching thread:
//cria e exibe uma aplicacao GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
criaExibeGUI();
}
});
}
}

Resultado:

FasesDaLua

Demo Look Feel

Código:

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

public class LFDemo extends JFrame{
private UIManager.LookAndFeelInfo[] looks = UIManager.getInstalledLookAndFeels();
private JLabel lbLabel01 = new JLabel("Nome :");
private JLabel lbLabel02 = new JLabel("E-mail :");
private JTextField jtTexto01 = new JTextField( 10 );
private JTextField jtTexto02 = new JTextField( 10 );
private JButton jbOk = new JButton("Enviar");
private JButton jbLim = new JButton("Limpar");
private JRadioButton[] escolha = new JRadioButton[ looks.length ];
private ButtonGroup grupo = new ButtonGroup();


public static void main( String[] args ){
LFDemo lfd = new LFDemo();
lfd.setVisible(true);
}

public LFDemo(){
super("Selecione um LF");
Container c = getContentPane();
// Usa o gerenciador FlowLayout(fluxo)
c.setLayout ( new FlowLayout());
c.add(lbLabel01);
c.add(jtTexto01);
c.add(lbLabel02);
c.add(jtTexto02);
c.add(jbOk);
c.add(jbLim);
ItemSelecionado iselect = new ItemSelecionado();
for (int i = 0; i < looks.length; i++){
escolha[i] = new JRadioButton( looks[i].getName() );
escolha[i].addItemListener( iselect );
grupo.add( escolha[i] );
c.add( escolha[i] );
}
escolha[2].setSelected( true );
setDefaultCloseOperation( EXIT_ON_CLOSE );
setSize(200,250);
}

public void atualiza(int i){
try {
UIManager.setLookAndFeel(looks[i].getClassName());
SwingUtilities.updateComponentTreeUI(this);
}catch(Exception e) {
e.printStackTrace();
}
}

private class ItemSelecionado implements ItemListener {
public void itemStateChanged( ItemEvent e) {
for (int i=0; i < escolha.length; i++){
if (escolha[i].isSelected())
atualiza(i);
}
}
}
}

Resultado:

LFDemo LFDemo LFDemo

Autores: Carlos Fernando Gonçalves e Marli Esprega Gonçalves (Antares Information Systems)