A comunicação entre os diversos widgets é feita através de eventos (events, em inglês) e de action listeners. Os conceitos estão explicados no livro Programação em GUI, capítulo Eventos, sinais, slots e callbacks.
Primeira tentativa
editarO objetivo é criar um programa que mostre um botão (com a string OK) e uma caixa de texto. Ao clicar-se no botão, a caixa de texto responde, apresentando a string OK.
Para começar, vamos escrever o esqueleto do programa:
// arquivo swing_button_1.java
// inicio do programa swing_button - versao 1.0
import javax.swing.*; //All swing components live
//in the javax.swing package
import java.awt.*;
import java.awt.event.*;
// many widgets under a box
public class swing_button_1 {
public static void main(String[] args) {
// creates the Frame
JFrame frame = new JFrame("swing_button_1");
// defines frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// creates the (vertical) box
Box vbox = new Box(BoxLayout.Y_AXIS);
// places the box inside the frame
frame.add(vbox);
// creates the elements of the vbox
// creates the button
JButton button1 = new JButton("OK");
JTextField entry1 = new JTextField("");
// add button and textfield inside the vbox
vbox.add(button1);
vbox.add(entry1);
// set frame to a decent size (default is a small frame)
frame.setSize(212, 258);
// makes frame (and everything in it) visible
frame.setVisible(true);
}
}
// fim do programa swing_button - versao 1
O programa acima não faz nada: pode-se clicar no botão, mas isto não tem efeitos. Precisamos incluir dois elementos:
- o botão button1 deve incluir um actionListener, para que o clicar nele tenha algum efeito
- a caixa de texto entry1 deve incluir um actionPerformed, para que ela reaja ao clicar do botão
Incluir um actionListener no botão é muito simples: basta chamar o membro addActionListener, passando como argumento um objeto do tipo ActionListener:
button1.addActionListener(al);
Já a criação do actionListener é mais complicada. Um actionListener deve ter um membro actionPerformed; assim, poderíamos ter:
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
};
A versão preliminar do código, que ainda não faz aparecer "OK" na caixa de texto, mas faz aparecer "OK" na console, é:
// programa swing_button_1.java
// inicio do programa swing_button - versao 1.1
import javax.swing.*; //All swing components live
//in the javax.swing package
import java.awt.*;
import java.awt.event.*;
// many widgets under a box
public class swing_button_1 {
public static void main(String[] args) {
// creates the Frame
JFrame frame = new JFrame("swing_button_1");
// defines frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// creates the (vertical) box
Box vbox = new Box(BoxLayout.Y_AXIS);
// places the box inside the frame
frame.add(vbox);
// creates the elements of the vbox
// creates the button
JButton button1 = new JButton("OK");
JTextField entry1 = new JTextField("");
// ActionListener: makes button1 iteract with the System
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("OK");
}
};
// add ActionListener to the button
button1.addActionListener(al);
// add button and textfield inside the vbox
vbox.add(button1);
vbox.add(entry1);
// set frame to a decent size (default is a small frame)
frame.setSize(212, 258);
// makes frame (and everything in it) visible
frame.setVisible(true);
}
}
// fim do programa swing_button - versao 1.1
E aqui a coisa se complica: não dá para simplesmente trocar a variável al para:
// ActionListener: makes button1 iteract with entry1
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
entry1.setText("OK");
}
};
porque o compilador dá erro, com uma mensagem incompreensível (Cannot refer to a non-final variable entry1 inside an inner class defined in a different method).
Solução orientada a objetos
editarA solução para este programa está em reescrever a classe swing_button_1 de forma a aproveitar as vantagens da programação orientada a objetos.
Assim, teremos uma classe swing_button_2 que, em vez de conter apenas um main e fazer tudo usando variáveis locais do main, é, ela própria, uma classe do Swing.
Por exemplo, quase todos widgets que foram criados no main podem se tornar membros da classe swing_button_2, sendo esta uma subclasse do widget principal.
Um esboço da reorganização, com o código que mostra os widgets mas não faz nada, seria:
// programa swing_button_2.java
// inicio do programa swing_button - versao 2.0
import javax.swing.*; //All swing components live
//in the javax.swing package
import java.awt.*;
import java.awt.event.*;
// a classe swing_button_2 antes era subclasse de Object
// agora, torna-se subclasse de JFrame
public class swing_button_2 extends JFrame {
// os widgets que eram criados no main
// agora são membros da classe
static Box vbox;
static JButton button1;
static JTextField entry1;
public static void main(String[] args) {
// o frame é criado no main (como antes)
// a diferença é que chamamos o constructor da classe
// este constructor se encarrega de montar vbox, button1 e entry1
swing_button_2 frame = new swing_button_2("swing_button_2");
// o resto é igual
frame.add(vbox);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(212, 258);
frame.setVisible(true);
}
// o trabalho de criar os widgets vbox, button1 e entry1 é feito no constructor da classe
public swing_button_2(String title) {
// super chama o constructor da classe JFrame
super(title);
// o resto é igual
vbox = new Box(BoxLayout.Y_AXIS);
button1 = new JButton("OK");
entry1 = new JTextField("");
vbox.add(button1);
vbox.add(entry1);
}
}
// fim do programa swing_button - versao 2.0
Incluindo o ActionListener
editarComo visto acima, precisamos agora adicionar um ActionListener ao widget button1, e precisamos que este ActionListener tenha o método actionPerformed.
A forma mais natural de fazer isto é tornar o próprio frame um ActionListener, o que pode ser feito trocando-se a definição da classe de:
public class swing_button_2 extends JFrame {
para
public class swing_button_2 extends JFrame implements ActionListener {
Então, todos objetos da classe swing_button_2, além dos métodos da classe JFrame, também herdarão os métodos da classe ActionListener, que, no caso, é apenas um: actionPerformed. Este método deve ser escrito:
public void actionPerformed(ActionEvent e) {
entry1.setText("OK");
};
Finalmente, o membro button1 do objeto frame deve se conectar ao objeto frame, de forma que o método actionPerformed do frame seja executado quando o botão for clicado. Assim, temos que fazer:
button1.addActionListener(this);
Código, versão final
editarA versão final do código fica:
// programa swing_button_2.java
// inicio do programa swing_button - versao 2.1
import javax.swing.*; //All swing components live
//in the javax.swing package
import java.awt.*;
import java.awt.event.*;
// a classe swing_button_2 antes era subclasse de Object
// agora, torna-se subclasse de JFrame e implementa as
// interfaces da classe ActionListener
public class swing_button_2 extends JFrame implements ActionListener {
// os widgets que eram criados no main
// agora são membros da classe
static Box vbox;
static JButton button1;
static JTextField entry1;
// ActionListener faz button1 iteragir com entry1
public void actionPerformed(ActionEvent e) {
entry1.setText("OK");
};
public static void main(String[] args) {
// o frame é criado no main (como antes)
// a diferença é que chamamos o constructor da classe
// este constructor se encarrega de montar vbox, button1 e entry1
swing_button_2 frame = new swing_button_2("swing_button_2");
// o resto é igual
frame.add(vbox);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(212, 258);
frame.setVisible(true);
}
// o trabalho de criar os widgets vbox, button1 e entry1 é feito no constructor da classe
public swing_button_2(String title) {
// super chama o constructor da classe JFrame
super(title);
// o resto é igual
vbox = new Box(BoxLayout.Y_AXIS);
button1 = new JButton("OK");
entry1 = new JTextField("");
// button1 ganha um ActionListener
button1.addActionListener(this);
vbox.add(button1);
vbox.add(entry1);
}
}
// fim do programa swing_button - versao 2.1
Ligações externas
editar- Writing Event Listeners (tutorial em inglês)