I think you can change your logic a little bit by applying the tip @jean said in the comments, also changing the way you validate operations. I made an example to explain better in the answer.
Screen construction
The print below contains a screen with two JTextField
: a call fieldValorAnterior
, which is smaller and sits higher at the top to display the partial account and another call fieldValorAtual
just below, glued to the fieldValorAnterior
which will display the numbers as they are clicked.
Also contains numeric buttons, floating point and basic operations.
Creation of listeners
Assuming that your numeric buttons have as text the unit value of 0 to 9, you can make a listener
unique to them, whose only function is to concatenate the existing value with the new value clicked:
class AcaoBotaoNumericoListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
String valorAtual = fieldValorAtual.getText();
fieldValorAtual.setText(valorAtual + btn.getText());
}
}
Just apply that to the buttons ActionListener
:
this.btn0.addActionListener(new AcaoBotaoNumericoListener());
// ...
this.btn9.addActionListener(new AcaoBotaoNumericoListener());
Also assuming you have operator buttons whose text is the corresponding operator itself, just create a actionListener
that will handle the content when an operation button is clicked:
class AcaoBotaoOperacaoListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
String valorAtual = fieldValorAtual.getText();
String valorAnterior = fieldValorAnterior.getText();
if (!valorAtual.isEmpty() && !valorAnterior.isEmpty()) {
fieldValorAtual.setText("");
fieldValorAnterior.setText(efetuarCalculo(valorAnterior, valorAtual) + " " + btn.getText());
} else if (!valorAtual.isEmpty() && valorAnterior.isEmpty()) {
fieldValorAtual.setText("");
fieldValorAnterior.setText(valorAtual + " " + btn.getText());
} else if (valorAtual.isEmpty() && !valorAnterior.isEmpty()) {
fieldValorAnterior.setText(valorAnterior.substring(0, valorAnterior.length() - 1) + btn.getText());
}
}
}
Note that the last condition changes the signal of the current operation, similar to the Windows calculator. The first condition will perform the calculation and concatenate with the new clicked operator, since both textfields have values, and the fieldAnterior
will always be either empty or contain a number and a sign separated by space (I explain why to use space). The second condition will only concatenate the value with the operator and display in the fieldAnterior
.
To apply the action to buttons:
this.btnAdicao.addActionListener(new AcaoBotaoOperacaoListener());
this.btnSubtracao.addActionListener(new AcaoBotaoOperacaoListener());
this.btnMultiplicacao.addActionListener(new AcaoBotaoOperacaoListener());
this.btnDivisao.addActionListener(new AcaoBotaoOperacaoListener());
Now the boot =
needs a listener
the part:
this.btnIgual.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String valorAtual = fieldValorAtual.getText();
String valorAnterior = fieldValorAnterior.getText();
if (!valorAtual.isEmpty() && !valorAnterior.isEmpty()) {
fieldValorAtual.setText(efetuarCalculo(valorAnterior, valorAtual));
}
}
});
Note that the account will only be processed if it has values in both fields, if this condition is not met, we will not have 2 values and a signal to pass to the class OperacaoAritmetica
.
The Operacaoaritmetica class
Finally, the method responsible for passing these values to our class OperacaoAritmetica
:
private String efetuarCalculo(String valorAnterior, String valorAtual) {
String valores[] = (valorAnterior + " " + valorAtual).split("\\s");
OperacaoAritmetica operacao = new OperacaoAritmetica(valores[1], Double.parseDouble(valores[0]), Double.parseDouble(valores[2]));
fieldValorAnterior.setText("");
String resultado;
try {
double res = operacao.calcular();
resultado = res % 1 == 0 ? Math.round(res) + "" : res + "";
} catch (ArithmeticException ex) {
resultado = "!ERROR";
}
return resultado;
}
The condition res % 1 == 0
checks whether the double returned is an exact integer, and converts to int
, just to avoid an unexpected zero as in 1 + 3 = 4.0. I used the split
so that it would be possible, in a simpler way, to separate the 3 values (value 1, value 2 and operator), so space was used in the listener
of the operating buttons.
To perform the operations (and following the idea already passed in the comments), you can create a class that receives the operator’s signal and the two values to be calculated, and in this class, implement all 4 operations (careful division by zero!) that will be our class OperacaoAritmetica
:
public class OperacaoAritmetica {
private final String SOMA = "+";
private final String SUBTRACAO = "-";
private final String MULTIPLICACAO = "*";
private final String DIVISAO = "/";
private String operacao;
private double valor1;
private double valor2;
public OperacaoAritmetica(String sinal, double valor1, double valor2) {
this.valor1 = valor1;
this.valor2 = valor2;
this.operacao = sinal;
}
public double calcular() {
switch (operacao) {
case SOMA:
return somar(valor1, valor2);
case SUBTRACAO:
return subtrair(valor1, valor2);
case MULTIPLICACAO:
return multiplicar(valor1, valor2);
case DIVISAO:
return dividir(valor1, valor2);
default:
throw new IllegalArgumentException("Operador não é válido");
}
}
private double somar(double valor1, double valor2) {
return valor1 + valor2;
}
private double subtrair(double valor1, double valor2) {
return valor1 - valor2;
}
private double multiplicar(double valor1, double valor2) {
return valor1 * valor2;
}
private double dividir(double valor1, double valor2) {
if (valor2 == 0) {
throw new ArithmeticException("Não é possivel dividir por zero.");
}
return valor1 / valor2;
}
}
If you want to upgrade even more with that floating point button, just add one listener
thus:
this.btnPontoSeparador.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String strValorAtual = fieldValorAtual.getText();
String strpontoFlutuante = ((JButton) e.getSource()).getText();
if (!strValorAtual.contains(".") && strValorAtual.isEmpty()) {
strValorAtual = "0" + strpontoFlutuante;
} else if (!strValorAtual.contains(".") && !strValorAtual.isEmpty()) {
strValorAtual += strpontoFlutuante;
}
fieldValorAtual.setText(strValorAtual);
}
});
If the value is blank, it will fill in with 0.
, if not, it will only concatenate the same point.
And also the Clear button:
this.btnLimpar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fieldValorAnterior.setText("");
fieldValorAtual.setText("");
}
});
}
This gives you a sense of how to create a very basic calculator similar to windows. Of course this example did not treat how to recover a negative value, among other things that could be done, but it was just an example, the rest you can break your head and try to implement.
At this link there is a complete and functional example, which can be tested.
Is the code too long? Just with this, I could not understand well the logic you are using to create a calculator.
– user28595
Yes, the IDE I use points out that I spent 469 lines of code. But if I had my actionPerformed method it would help you to understand better?
– Marcos Paes
Edit the question and explain how you are storing the numeric values and operators as well.
– user28595
Create a class Expression and generic methods to retrieve and edit the expression. Your buttons will call these methods by passing the edited text. In practice think that logic is in the class, your buttons merely call these methods passing appropriate parameters to each button
– jean
Rectify my explanation I hope I’ve helped
– Marcos Paes
I put another part of my code to show how I get the first and second nu8mero, Diego F.
– Marcos Paes
Are you using
swing
right?– user28595
Yes I am using @Diego f
– Marcos Paes
I don’t think your approach is very good on how to store information. I am now unable to move the IDE, as soon as I can, I reply here.
– user28595
Thank you, I will try to resolve as @jean suggested. I look forward to your reply
– Marcos Paes
Look, I found some answers that might help you, my answer will end up looking like a "tutorial", and this type of answer is not recommended on the site, especially when you have one or more good answers. Look at the ones on Calculator with Java Graphical Interface and How to do basic mathematical operations?. I believe they will be much more than you need to solve the problem. :)
– user28595
Another problem is that you are converting to
String
of the display, with non-principated characters (i.e., not numbers), in the case of the error, the/
, and the parse will always pop aNumberFormatException
every time you find a character that you can’t convert to integer. try to separate the entered values from the operation, and if you want to display everything on the display, just concatenate them. So you can handle different numbers and operations and variables, avoiding the problem ofNumberFormatException
.– user28595
Marcos, if the answer answered it, it would be interesting to mark it as accepted, thus, serve as reference for other users. :)
– user28595