Nada melhor que criar seu jogo para aprender Java.
Uma aplicação simples usando JFrame, JButton, JLabel e JTextField
Quando se pensa em programar, logo se pensa em criar uma nova versão de Quake III - Arena ou um novo sistema operacional que não trave e seja super seguro.
Porém, com o passar do tempo, vemos que estamos usando somente a linha de comando do Shell ( ou do DOS, caso você ainda não tenha visto a luz), e sua namorada não aguenta mais testar aqueles joguinhos naquela maldita tela preta.
Uma das vantagens do Java é a facilidade (?) de criar aplicativos com interface gráfica.
Pra ilustrar o uso desses elementos gráficos, vou mostrar como criar esse simples jogo, que gera um número e você tem que adivinhar o número através das dicas.
Então vamos lá, começando por alguns dos principais elementos:
- JFrame
Frame é uma uma moldura, ou uma janela. Sabe aquela janelinha do programa? É um frame.
Sabe quando clica em algo, geralmente um botão, e abre outra janelinha? Aquela outra janela é outro frame.
Cada uma delas é representada por uma classe. Se uma janela surge dentro de outra, tem a ver com herança. Se uma janela pode se apresentar de várias formas, mas com a mesma base de outras, tem a ver com polimofirsmo (note a importância das classes).
- JLabel
Label é simplesmente um texto, ou rótulo, ao pé da letra.
- JTextField
É o campo de texto (sabendo inglês, muitas coisas são óbvias) onde você vai escrever. É onde você vai enviar string (texto) pro programa, é uma espécia de canal de comunicação entre o usuário e o programa.
Com base nesses simples elementos, iremos criar um joguinho (nada de 'hello world', você pode até enviar pros seus amigos).
O programa gera um número, entre 1 e 1000, aleatoriamente, e você tem que adivinhar que número é esse. Se o seu palpite for maior ou menor que o número gerado, o programa avisa isso, até você acertar o dito cujo.
Criando o Frame principal
Vamos usar somente um frame nesse aplicativo, um Frame simples, com um texto (label), um campo pra você introduzir o número, um botão pra testar se o seu palpite está certo e outro pra gerar um número aleatório, para jogar novamente.
Vamos chamar nosso frame de window:
public class window extends JFrame
{
}
Pra usar a JFrame precisamos adicionar:
import javax.swing.JFrame;
Tudo que queremos exista nesse frame, colocamos dentro dessa classe.
private JButton generateButton; // gerar outro número
private JButton guessButton; // testar seu palpite
private JTextField textField; // campo de texto
private JLabel guess; // texto "Digite um numero, de 1 até 1000"
private int number, attemp; // number é o número gerado aleatoriamente, attemp é o nosso palpite
Pra usar esses elementos (JComponents), precisamos importar:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
Essas são variáveis globais dentro da nossa classe window.
Método pra gerar um número aleatório:
public void generate()
{
Random gen = new Random();
number = gen.nextInt(1000) + 1;
}
Para usar, precisamos importar:
import java.util.Random;
Título do programa
O seguinte código criar o título, que fica na parte de cima do Frame, perto dos botões minimizar, maximizar e fecha:
super("Adivinhe o Número 1.0 - by Emerson, Lake & Palmer");
A próxima linha é simplesmente pra definir o Layout do frame:
setLayout(new FlowLayout());
Pra usar, importe:
import java.awt.FlowLayout;
Depois, gere o número:
generate();
Usando o campo de texto
Já declaramos a JTextField, agora vamos especificar suas características, como o tamanho do campo:
textField = new JTextField(27);
Criar não significa que vai aparecer, pra aparecer no Frame usamos:
add(textField);
Vamos agora criar um handler, uma classe para lidar com o campo de texto. Isso é, quando você digita e aperta enter, a informação vai para o programa. O handler trata como e quando essa mensagem vai, o programa não tem como adivinhar quando você quer que o número digitado seja enviado.
Criamos o handler assim (mais tarde vamos criar a classe TextFieldHandler):
TextFieldHandler handler = new TextFieldHandler();
Vamos definir que esse handler é que vai lidar com o JComponent textField:
textField.addActionListener(handler);
addActionListener : é um comando interno, que, como o nome diz, espera a ação acontecer pra passar a informação pro programa.
Para usar, devemos importar:
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
Usando com o botão Testar
Exatamente como fizemos com o JTextField, fazemos com um JButton. Ou seja, precisamos de um handler pro programa saber quando clicamos no botão.
A única diferença aqui é que podemos escrever algo no JButton ("Testar", no caso):
GuessButton guess = new GuessButton();
guessButton = new JButton("Testar");
guessButton.addActionListener(guess);
add(guessButton);
Usando o botão Gerar número
Handler, que espera o usuário clicar no botão para passar essa informação pro programa:
GenerateAnotherNumber generateAnotherNumber = new GenerateAnotherNumber ();
generateButton = new JButton("Gerar outro número");
generateButton.addActionListener(generateAnotherNumber);
add(generateButton);
Handler: TextFieldHandler
Os handlers usam todos a classe ActionListener, que é uma classe geralzona, para o tratamento de ações.
public class TextFieldHandler implements ActionListener
{
}
A ActionListener possui um método chamado ActionPerformed, que recebe um evento como argumento (um enter, um click do mouse etc):
public void actionPerformed (ActionEvent event)
{
}
Aqui, o nosso evento é uma variável chamada 'event'.
Quando ela vem da textField, o seguinte if retorna verdadeiro:
if(event.getSource() == textField)
Quando digitamos algo e apertamos enter, o que foi digitado fica na seguinte string:
event.getActionCommand()
Vamos passar o que foi digitado, que é uma string, pra inteiro:
attemp = Integer.parseInt(event.getActionCommand());
Agora vamos para a lógica super complexa do programa.
Caso o nosso palpite seja maior que o número, aparece uma janela dizendo que o palpite é maior.
Caso seja menor, aparece dizendo que é menor.
Caso não seja maior nem menor...exato, Watson.
A janelinha com o texto é a JOptionPane, que recebe dois argumentos: uma referência ao frame (podemos ter vários frames numa mesma aplicação) e uma string.
Para usa-la, devemos importar:
import javax.swing.JOptionPane;
A lógica, que ficará dentro do método test(int attemp), fica:
if(attemp < number)
JOptionPane.showMessageDialog(window.this,"Errou. o número é maior");
else if(attemp > number)
JOptionPane.showMessageDialog(window.this,"Errou, o número é menor");
else
{
JOptionPane.showMessageDialog(window.this,"Parabéns, voce acertou o numero!");
textField.setEditable(false);
}
esse textField.setEditable(false) não permite que algo seja digitado, e acontece quado você acerta o número.
Handler: GenerateButton
Também é uma ActionListener e também possui uma função actionPerformed, e dentro desta:
if(event.getSource() == generateButton)
{
generate();
textField.setEditable(true);
textField.setText("");
}
Ou seja, após gerar um número, faz com que o campo de texto seja editável e apaga o que tem escrito lá (colocando uma string nula).
Handler: GuessButton
A diferença desse handler é que ele pega o que tem escrito no campo de texto, através do comando:
stringNumber=textField.getText();
Onde stringNumber é uma String pra armazenar o que tem escrito no campo de texto.
Depois passamos essa string pra inteiro e fazemos a mesma lógica do TextFieldHandler.
Pronto, frame criado.
Mas criar/existe é algo, aparecer é outro.
E se existirem milhares de frames, vão todos aparecer? Não.
O que foi explanado é só a classe window.
Vamos criar a classe principal do jogo, que criar a JFrame window, dizer o tamanho dela, se é visível e o que ocorre quando clicamos em Fechar (se minimiza ou realmente fecha o aplicativo, que é o caso).
Isso é feito, na main, assim:
window mainWindow = new window();
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(400,150);
mainWindow.setVisible(true);
Pra usar a JFrame, importe:
import javax.swing.JFrame;
Arquivos .java
GuessTheNumber.java
import javax.swing.JFrame;
public class GuessTheNumber
{
public static void main(String[] args)
{
window mainWindow = new window();
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(400,150);
mainWindow.setVisible(true);
}
}
window.java
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import java.util.Random;
public class window extends JFrame
{
private JButton generateButton;
private JButton guessButton;
private JTextField textField;
private JLabel guess;
private int number, attemp;
public void generate()
{
Random gen = new Random();
number = gen.nextInt(1000) + 1;
}
public void test(int attemp)
{
if(attemp < number)
JOptionPane.showMessageDialog(window.this,"Errou. o número é maior");
else if(attemp > number)
JOptionPane.showMessageDialog(window.this,"Errou, o número é menor");
else
{
JOptionPane.showMessageDialog(window.this,"Parabéns, voce acertou o numero!");
textField.setEditable(false);
}
}
public window()
{
super("Adivinhe o Número 1.0 - Programação Progressiva");
setLayout(new FlowLayout());
generate();
//frase principal, pedindo o numero
guess = new JLabel();
guess.setText("Digite um numero, de 1 até 1000");
add(guess);
//adicionando o campo de texto
textField = new JTextField(27);
add(textField);
TextFieldHandler handler = new TextFieldHandler();
textField.addActionListener(handler);
//handler pro botao guessButton
GuessButton guess = new GuessButton();
guessButton = new JButton("Testar");
guessButton.addActionListener(guess);
add(guessButton);
//handler pro botao generateButton
GenerateAnotherNumber generateAnotherNumber = new GenerateAnotherNumber ();
generateButton = new JButton("Gerar outro número");
generateButton.addActionListener(generateAnotherNumber);
add(generateButton);
}
public class TextFieldHandler implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
//se o evento for enter
if(event.getSource() == textField)
{
attemp = Integer.parseInt(event.getActionCommand());
attemp = Integer.parseInt(event.getActionCommand());
test(attemp);
}
}
}
private class GenerateAnotherNumber implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == generateButton)
{
generate();
textField.setEditable(true);
textField.setText("");
}
}
}
private class GuessButton implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == guessButton)
{
String stringNumber;
stringNumber=textField.getText();
attemp = Integer.parseInt(textField.getText());
test(attemp);
}
}
}
}
ou
A abordagem anterior foi um pouco mais OO, orientada a objetos, com um handler para cada possível evento diferente. Mas note que todos são ActionListener e usam a actionPerformed e criamos variáveis não obrigatórias (stringNumber e attemp). O código a seguir é mais enxuto. Por ser simples, não há problemas usar ele assim, mas caso fosse um projeto maior, é sempre bom primar pela organização (pois é necessário manter o código, depois). window.java
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import java.util.Random;
public class window extends JFrame
{
private JButton generateButton;
private JButton guessButton;
private JTextField textField;
private JLabel guess;
private int number;
public void generate()
{
Random gen = new Random();
number = gen.nextInt(1000) + 1;
}
public void test(int attemp)
{
if(attemp < number)
JOptionPane.showMessageDialog(window.this,"Errou. o número é maior");
else if(attemp > number)
JOptionPane.showMessageDialog(window.this,"Errou, o número é menor");
else
{
JOptionPane.showMessageDialog(window.this,"Parabéns, voce acertou o numero!");
textField.setEditable(false);
}
}
public window()
{
super("Adivinhe o Número 1.0 - by Emerson, Lake & Palmer");
setLayout(new FlowLayout());
generate();
//frase principal, pedindo o numero
guess = new JLabel();
guess.setText("Digite um numero, de 1 até 1000");
add(guess);
//criando e adicionando os handlers
Handler handler = new Handler();
textField = new JTextField(27);
textField.addActionListener(handler);
add(textField);
guessButton = new JButton("Testar");
guessButton.addActionListener(handler);
add(guessButton);
generateButton = new JButton("Gerar outro número");
generateButton.addActionListener(handler);
add(generateButton);
}
public class Handler implements ActionListener
{
@Override
public void actionPerformed (ActionEvent event)
{
//se o evento for enter
if(event.getSource() == textField)
test( Integer.parseInt( event.getActionCommand() ) );
//se o evento for um click no botoão gerar outro número
else if(event.getSource() == generateButton)
{
generate();
textField.setEditable(true);
textField.setText("");
}
//se o evento for um click no botão testar
else if(event.getSource() == guessButton)
test( Integer.parseInt( textField.getText() ) );
}
}
}