Problems with swing calculator operations

Asked

Viewed 743 times

3

I need to make a calculator that works like the windows. I’m having trouble at the moment the user can change the type of operation 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 method Integer.parseInt(taVisor.getText()) and when it squeezes some operator(+,-,*,/), I start storing in a String. By pressing equal(=), it checks what is in my string and carries out the operation.

Below is my code. The error that gives:

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));
     }
  • Is the code too long? Just with this, I could not understand well the logic you are using to create a calculator.

  • 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?

  • Edit the question and explain how you are storing the numeric values and operators as well.

  • 2

    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

  • Rectify my explanation I hope I’ve helped

  • I put another part of my code to show how I get the first and second nu8mero, Diego F.

  • Are you using swing right?

  • Yes I am using @Diego f

  • 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.

  • Thank you, I will try to resolve as @jean suggested. I look forward to your reply

  • 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. :)

  • 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 a NumberFormatException 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 of NumberFormatException.

  • Marcos, if the answer answered it, it would be interesting to mark it as accepted, thus, serve as reference for other users. :)

Show 8 more comments

1 answer

5

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.

inserir a descrição da imagem aqui

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.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.