Calculadora - GUI

Galera estou montando o esqueleto de uma Calculadora para aprender a usar o Swing, porém estou com dificuldade em alinhar os botões, segue o código que fiz:

public class Formulario {
	private JFrame frame;
	private JPanel panelWest;

	private void montaFormulario() {
		frame = new JFrame("Calculadora");
		panelWest = new JPanel();
		JButton[] button = new JButton[5];

		button[0] = new JButton("7");
		button[1] = new JButton("8");
		button[2] = new JButton("9");
		button[3] = new JButton("4");
		button[4] = new JButton("5");

		for (int i=0; i<button.length; i++) {
			button[i].setPreferredSize(new Dimension(45, 30));
		}

		panelWest.add(button[0]);
		panelWest.add(button[1]);
		panelWest.add(button[2]);
		panelWest.add(button[3]);
		panelWest.add(button[4]);

		frame.getContentPane().add(BorderLayout.WEST, panelWest);
		frame.setSize(300, 300);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

Estou pensando em organizar ela em 4 partes, ou seja, criar 4 painéis:
1 - panelWest para os operandos
2 - panelCentral para os operadores
3 - panelEast para outros operadores
4 - panelNorth para a tela

Não consigo realizar a quebra de linha nos botões, estão saindo assim:

7 8 9 4 5

e eu gostaria que saíssem assim:

7 8 9 4 5

Oi, eu usaria GridLayout no panelWest

Paulo estou tentando faze desta forma mas não tá dando "/

panelWest.setLayout(new GridLayout(3, 3));

O que estou fazendo errado?

é assim mesmo, qual erro tá dando?

vc tbm pode tentar:

panelWest = new JPanel( new GridLayout(3,3) ); 

Faltou limpar o projeto, hehe. Agora funcinou. Olha meu código:

package swingbasico;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;

public class CalculadoraGUI {
	private JFrame frame;
	private JPanel panelWest, panelCentral, panelNorth, panelEast;
	private JButton[] buttonWest, buttonCenter, buttonEast;
	private JTextField textFieldNorth;

	private void makeGUI() {
		frame = new JFrame("Calculadora");
		panelWest = new JPanel();
		panelCentral = new JPanel();
		panelNorth = new JPanel();
		panelEast = new JPanel();

		buttonWest = new JButton[9];
		buttonCenter = new JButton[4];
		buttonEast = new JButton[1];
		textFieldNorth = new JTextField(10);

		//criar botoes da regiao oeste
		buttonWest[0] = new JButton("7");
		buttonWest[1] = new JButton("8");
		buttonWest[2] = new JButton("9");
		buttonWest[3] = new JButton("4");
		buttonWest[4] = new JButton("5");
		buttonWest[5] = new JButton("6");
		buttonWest[6] = new JButton("1");
		buttonWest[7] = new JButton("2");
		buttonWest[8] = new JButton("3");

		//criar botoes da regiao central
		buttonCenter[0] = new JButton("/");
		buttonCenter[1] = new JButton("*");
		buttonCenter[2] = new JButton("-");
		buttonCenter[3] = new JButton("+");

		//criar botoes da regiao leste
		buttonEast[0] = new JButton("=");


		for (int i=0; i<buttonWest.length; i++) {
			buttonWest[i].setPreferredSize(new Dimension(45, 30)); //defir tamanho dos botoes da painel oeste
			panelWest.add(buttonWest[i]); //adicionar botoes ao painel oeste
		}

		for (int i=0; i<buttonCenter.length; i++) {
			buttonCenter[i].setPreferredSize(new Dimension(50, 30)); //definiar tamahno do botoes do painel central
			panelCentral.add(buttonCenter[i]); //adicionar bootoes ao painel central
		}

		buttonEast[0].setPreferredSize(new Dimension(35, 30));
		panelNorth.add(textFieldNorth); //adicionar campo de texto ao painel norte
		panelEast.add(buttonEast[0]); //adicionar botao ao painel leste

		panelCentral.setLayout(new GridLayout(0,1));
		panelWest.setLayout(new GridLayout(3, 3));
		panelEast.setLayout(new GridLayout(0,1));

		frame.getContentPane().add(BorderLayout.CENTER, panelCentral);
		frame.getContentPane().add(BorderLayout.WEST, panelWest);
		frame.getContentPane().add(BorderLayout.NORTH, panelNorth);
		frame.getContentPane().add(BorderLayout.EAST, panelEast);
		frame.setResizable(false);
		frame.pack();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) throws ClassNotFoundException {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}
		new CalculadoraGUI().makeGUI();
    }
}

Agora vou começar a implementar os métodos actionPerformed de cada botão, contudo estou em dúvida de como organizar o código, será que se colocar tudo ai vai ficar bagunçado? Ou será que crio outra classe só pra chamar os actionPerformed?
Aceito sugestões quando a estruturação :smiley:

cara vc pode criar outra classe sim fica mais organizado

outra coisa que sugiro :slight_smile: ao invés de especificar aquele tanto de import no começo do código usa o

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

é melhor e economiza espaço kkk

Primeiro vou tentar fazer tudo na mesma classe dpois organizo pois ta complicado, hehe.
Estou com dificuldade de saber de qual botão está vindo o ActionEvet, estou fazendo assim:

	public void actionPerformed(ActionEvent e) {
		if (e == buttonWest[0]) {
		
		}
		String texto = buttonWest[0].getText();
		textFieldNorth.setText(texto);
	}

Como faço pra no metodo actionPerformed saber qual botão está sendo ouvido?
Deixei as imports assim pra eu saber exatamente com qual classe estrou trabalhando, hehe.

vc tem que especificar pro actionPerformed qual botão fará o que quando sofrer a ação

usando array vai meio complicado pra saber qual botão colocar

Consegui fazer usando classes internas, mas agora não faço idéia de como fazer a operação, soma, divisão e talz.
Seria isso?

	class ButtonListner implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			String texto = buttonWest[0].getText();
			textFieldNorth.setText(texto);
		}
	}

	class ButtonListner1 implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			String texto = buttonCenter[0].getText();
			textFieldNorth.setText(texto);
		}
	}

vc pode usar o metodo getSource()
ai fica vc usa um unico actionListener…
ai fika tipo:

if(e.getSource()==botao1){ fazAlgumaCoisa(); } if(e.getSource()==botao2){ fazOutraCoisa(); }
sacou!?

o jeito que nosso colega disse é o mais manero

de if e tasls pra fazer as operações vc pode criar um método pra isso olha o exemplo de uma calculadora aki

[code] public void actionPerformed(ActionEvent e) {

	converter(); //Metodo para pegar dados e converter
	if(e.getSource() == bt_somar || e.getSource() == mi_somar)
	{
		resultado = num1 + num2;
		//tf_resultado.setText(String.valueOf(resultado));			
	}

	if(e.getSource() == bt_subtrair || e.getSource() == mi_subtrair)
	{
		resultado = num1 - num2;			
	}

	if(e.getSource() == bt_multiplicar || e.getSource() == mi_multiplicar)
	{
		resultado = num1 * num2;			
	}

	if(e.getSource() == bt_dividir || e.getSource() == mi_dividir)
	{
		resultado = num1 / num2;			
	}
	
	exibe();	//Método para exibir resultado

	if(e.getSource() == bt_limpar || e.getSource() == mi_limpar)
	{
		tf_num1.setText("");
		tf_num2.setText("");
		tf_resultado.setText("");
		tf_num1.requestFocus();
	}

	if(e.getSource() == bt_sair || e.getSource() == mi_sair)
	{
		System.exit(0);
	}

}
public void converter()
{
	num1 = Double.parseDouble(tf_num1.getText());
	num2 = Double.parseDouble(tf_num2.getText());
}

public void exibe()
{
	tf_resultado.setText(""+calculo.format(resultado));
}

}
[/code]
Implementando uma interface

public interface Interface_1
{
       public void converter();
       public void exibe();
}

Não estou conseguindo encontrar a lógica pra pegar o valor dos números, numA e numB para realizar as operações "/

vc já adicionou ?

olha o exemplo

[code]bt_somar.addActionListener(this);
bt_subtrair.addActionListener(this);
bt_multiplicar.addActionListener(this);
bt_dividir.addActionListener(this);
bt_sair.addActionListener(this);
bt_limpar.addActionListener(this);

	mi_somar.addActionListener(this);
	mi_subtrair.addActionListener(this);
	mi_multiplicar.addActionListener(this);
	mi_dividir.addActionListener(this);
	mi_limpar.addActionListener(this);
	mi_sair.addActionListener(this);

[/code]


if(e.getSource() == bt_somar || e.getSource() == mi_somar)
		{
			double num1 = Double.parseDouble(tf_num1.getText());
			double num2 = Double.parseDouble(tf_num2.getText());
			double resultado = num1 + num2;
			//tf_resultado.setText(String.valueOf(resultado));
			tf_resultado.setText(""+resultado);
		}

vc tem que adicionar o objeto com objeto.addActionListener(this);

e depois vc pega os dados com o getText()

se puder posta o codigo aki

Consegui finalizar a calculadora com auxílio de um vídeo no youtube, só fiquei com dúvida em uma coisa:
Como ele consegue criar um método actionPerformed() para cada botão?
Segue o linl do vídeo http://www.youtube.com/watch?v=5hj3dpjJSzg&feature=BF&list=SP988E38135BA19BBA&index=3

ainda nao vi o video ( internet não ajuda ), mas pode ser assim:

botao.addActionListener( new ActionListener() {
           public void actionPerformed( ActionEvent e ) {

           }
});

Não foi desta forma não, ele consegue criar um ActionPerformed usando o nome de cada componente, por exemplo:

JButton button = new JButton()

e faz o ActionPerformed assim:

public void buttonActionPerformed() {}

Realmente fiquei perdido quando vi isso, se alguém tiver idéia. Obs.: ele cria a GUI usando o JFrameCreator do Netbeans, não sei se tem algo a ver.

O NetBeans cria uma classe anônima estendendo ActionListener e dentro dela ele chama o método citado. Mais ou menos assim:

[code]
// Dentro do construtor
btnOk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnOkActionPerformed(e);
}
});

btnCancelar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnCancelarActionPerformed(e);
}
});

. . .

// No corpo da classe
private void btnOkActionPerformed(ActionEvent e) {
. . .
}

private void btnCancelarActionPerformed(ActionEvent e) {
. . .
}[/code]Mas não é necessário criar este método, você pode colocar a implementação diretamente no método actionPerformed.

Usar Actions seria uma forma interessante de trabalhar as ações de uma calculadora: http://www.guj.com.br/java/140986-como-acionar-os-botoes-de-uma-calculadora-atraves-do-teclado

Estou quase entendendo, eu tinha lido que o correto seria usar classes internas, cada uma para escutar um componente diferente, ai cada classe interna implementaria ActionListener. Está um pouco diferente com classes anonimas e como não entendo sobre elas fiquei meio perdido, hehe.
Gostei deste artigo, vou ler com calma. Obrigado.

Classes anônimas também são classes internas. Se chamam de anônimas, pois não definimos um nome para elas. Elas geralmente são criadas na atribuição de uma variável de referência ou na passagem de um parâmetro (nosso caso).

btnOk.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { btnOkActionPerformed(e); } });
Neste trecho, foi definida uma classe anônima (sem nome), que implementa ActionListener, assim somos obrigados a implementar seus métodos abstratos, neste caso o actionPerformed.

No caso da calculadora, acho mais interessante criar Actions, assim pode atribuí-las aos botões e ainda registrá-las no InputMap para que sejam executadas a partir do teclado. Isso tudo está no artigo do ViniGodoy.

Cara usa a Visual Class, ia te facilitar muito nisso.