Problems with calculator operations made in swing

2

I need to make a calculator, which works like windows. I am having trouble at the moment the user can change the type of operation that he wants to perform.

For example, if he typed 10 + and wants to change the signal from + to -, he clicks the button that changes the operator. However, to store my first number, I use the Integer.parseInt(taVisor.getText()) method and when it hits some operator (+, -, *, /), I start storing in String . By pressing equal (=), it checks what is in my string and performs the operation.

Below is my code. The error that gives and that:

  

Exception in thread "AWT-EventQueue-0"   java.lang.NumberFormatException: For input string: "/"

if(evento.getSource()==bSomar){
         //Pega o meu primeiro valor
         a = Integer.parseInt(taVisor.getText());
         //Limpa o meu JtextField
         taVisor.setText("");
         //Adicona o meu sinal de +
         taVisor.setText(taVisor.getText()+"+");   
         taVisor.setFont(new Font("Ibama", 0, 20));
         //parte em estou tendo dificuldade 
         String texto4 = taVisor.getText();
         int qtda = texto4.length();
         boolean retval=true;
         if(retval == texto4.contains("texto4") && qtda==1)
         {
             texto4.replace(texto4,"+");
             //taVisor.setText("");
             taVisor.setFont(new Font("Ibama", 0, 20));
             taVisor.setText(texto4);
         }
      }

      if(evento.getSource()==bIgual)
  {
     texto = taVisor.getText();
     taVisor.setText("");

     boolean retval = true;
     if(retval == texto.contains("+"))//Verifica se a string tem aquele determinado numero de caracter ou se tem aquele caracter
     {
        String nova = texto.replace("+","");//Metodo que substitui um pedaco da string
        int numero = Integer.parseInt(nova);

        int resu = a + numero;

        String texto2 = String.valueOf(resu);

        taVisor.setText(texto2);
        taVisor.setFont(new Font("Ibama", 0, 20));
     }
    
asked by anonymous 28.03.2016 / 19:49

1 answer

5

I think you can change your logic a bit by applying the hint that @jean said in the comments, also changing the way you validate operations. I gave an example to explain better in the answer.

Screen construction

The print below contains a screen with two JTextField : one called fieldValorAnterior , which is smaller and is more at the top to display the partial account and another called fieldValorAtual bellow, pasted in fieldValorAnterior that will display the numbers as they are clicked.

Also contains numeric buttons, floating point, and basic operations.

Creatinglisteners

Assumingthatyournumericbuttonshaveaunitvalueof0to9,youcanmakeasinglelistenerforthem,whoseonlyfunctionistoconcatenatetheexistingvaluewiththenewclickedvalue:

classAcaoBotaoNumericoListenerimplementsActionListener{@OverridepublicvoidactionPerformed(ActionEvente){JButtonbtn=(JButton)e.getSource();StringvalorAtual=fieldValorAtual.getText();fieldValorAtual.setText(valorAtual+btn.getText());}}

JustapplythisActionListenertothebuttons:

this.btn0.addActionListener(newAcaoBotaoNumericoListener());//...this.btn9.addActionListener(newAcaoBotaoNumericoListener());

Alsoassumingyouhaveoperatorbuttonswhosetextisthecorrespondingoperator,justcreateaactionListenerthatwillhandlethecontentwhenanoperationbuttonisclicked:

classAcaoBotaoOperacaoListenerimplementsActionListener{@OverridepublicvoidactionPerformed(ActionEvente){JButtonbtn=(JButton)e.getSource();StringvalorAtual=fieldValorAtual.getText();StringvalorAnterior=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());
        }
    }
}

Notice that the last condition changes the signal of the current operation, similar to the Windows calculator. The first condition will calculate and concatenate with the new operator clicked, since both textfields have values, and fieldAnterior will always be either empty or contain a number and a sign separated by space (so I explain why use space). The second condition will only concatenate the value with the operator and display in fieldAnterior .

To apply the action to the buttons:

    this.btnAdicao.addActionListener(new AcaoBotaoOperacaoListener());
    this.btnSubtracao.addActionListener(new AcaoBotaoOperacaoListener());
    this.btnMultiplicacao.addActionListener(new AcaoBotaoOperacaoListener());
    this.btnDivisao.addActionListener(new AcaoBotaoOperacaoListener());

Now the = button 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 class OperacaoAritmetica .

The class OperationAritmetica

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;
}

Condition res % 1 == 0 checks whether the returned double is an exact integer, and converts to int , just so that an unexpected zero does not appear as in 1 + 3 = 4.0. I used the split so that it was possible, in a simpler way, to separate the 3 values (value 1, value 2 and operator), so space was used in listener of the operation buttons.

To perform 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 that class, implement all 4 operations (careful with 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 further refine that floating-point button, just add listener like this:

     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 with 0. , if it is 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("");
        }
    });
}

With this you can already have a sense of how to create a pretty basic calculator similar to windows. Of course this example did not address 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.

This link is a complete and functional example that can be tested.

    
29.03.2016 / 15:28