1

So I'm making a Java Calculator and walking into some errors upon clicking the function buttons (it compiles perfectly fine though). The error on the 1st line in my CMD was a NumberFormat Exception. After some searching I figured out that somewhere in my code I was trying to get a double out of an empty string (basically what I'm trying to do is parse a double from the label text). I'm guessing it's this part:

// if statement that puts the labels text into the first or second number
    if(firstNumber)
    {
        number1 = Double.parseDouble(label.getText().trim());
    } else {
        number2 = Double.parseDouble(label.getText().trim());
    }

Basically the problems are when i push the / * + or - button i get a NumberFormatExeption: For input string "/" etc. I can't quite figure out how i have to fix this error (I'm still (somewhat) a beginner in Java). Further down the line of errors (there were quite alot) were a whole lot of errors I didn't understand such as EventDispatchThread, EventQueue and many others. I couldn't find an explanation on my level of experience either so I'm asking for help here.

The numeric buttons all work fine.

At run: [http://gyazo.com/71cb4dde449ccf7ece44017388a71a0f]

Putting in numbers: [http://gyazo.com/5c7ab6c54ac6da180845c66866d66f8f]

All other buttons give errors in my CMD.

Here's my code (the spacing might be messed up in some parts):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
// import for Nimbus look
import javax.swing.UIManager.*;

public class Calculator extends JFrame implements ActionListener
{
    private JPanel bottom = new JPanel(); private JPanel top = new JPanel();
    private JLabel label = new JLabel(" ");
    private JButton[] buttons = new JButton[16];
    // booleans for calculator functions
    boolean add = false, substract = false, devide = false, multiply = false, firstNumber = true;
    // numbers that will be calculated
    double number1, number2;

    public Calculator()
    {
        setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));

        // bottom panel
        bottom.setPreferredSize(new Dimension(100,100));
        bottom.setLayout(new BorderLayout());

        //add bottom panel to frame
        add(bottom);

        // top panel
        top.setPreferredSize(new Dimension(300,400));
        top.setLayout(new GridLayout(4,4,3,3));
        top.setBackground(Color.BLACK);
        //dont add top panel to frame: you want top to be on bottom

        // add top panel to bottom panel
        bottom.add(top);

        // label
        label.setFont(new Font("Courier", Font.PLAIN, 20));
        label.setBackground(Color.BLACK);
        label.setForeground(Color.WHITE);
        label.setHorizontalAlignment(SwingConstants.RIGHT); // text is right-aligned
        label.setOpaque(true);

        // add the label to the bottom panel
        bottom.add(label, BorderLayout.NORTH);

        // creating buttons
        for(int i = 0; i < buttons.length; i++)
        {
            buttons[i] = new JButton("789/456*123+c0=-".substring(i, i+1));
            buttons[i].addActionListener(this);
           // add them to the top panel
           top.add(buttons[i]);
        }

        // Nimbus look
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
           // If Nimbus is not available, you can set the GUI to another look and feel.
           //set to default somehow o.o
        }

        // frame setters
        setTitle("Calculator");
        setSize(400,400);
        setVisible(true);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void Clear()
    {
        label.setText(" ");
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        //if's for all function buttons
        if(e.getSource() == buttons[3])
        {
           // devide
           devide = true;

           substract = false;
           add = false;
           multiply = false;

           firstNumber = false;
           Clear();

           label.setText("/");
        }

        if(e.getSource() == buttons[7])
        {
           // multiply
           multiply = true;

           substract = false;
           devide = false;
           add = false;

           firstNumber = false;
           Clear();

           label.setText("*");
        }

        if(e.getSource() == buttons[11])
        {
           // add
           add = true;

           substract = false;
           devide = false;
           multiply = false;

           firstNumber = false;
           Clear();

           label.setText("+");
        }

        if(e.getSource() == buttons[12])
        {
           // clear
           label.setText("0");
           number1 = 0.00;
           number2 = 0.00;

           add = false;
           substract = false;
           devide = false;
           multiply = false;

           firstNumber = true;
           Clear();
        }

        if(e.getSource() == buttons[15])
        {
           // substract
           substract = true;

           add = false;
           devide = false;
           multiply = false;

           firstNumber = false;
           Clear();

           label.setText("-");
        }

        // for loops that add the numbers on the buttons to the label
        for(int i = 0; i < 3; i++)
        {
           if(e.getSource() == buttons[i])
           {
               if(label.getText() == "0")
               {
                   label.setText("");
                   label.setText(label.getText() + buttons[i].getText());
               } else {
                   label.setText(label.getText() + buttons[i].getText());
               }
           }
        }

        for(int i = 4; i < 7; i++)
        {
           if(e.getSource() == buttons[i])
           {
               if(label.getText() == "0")
               {
                   label.setText("");
                   label.setText(label.getText() + buttons[i].getText());
               } else {
                   label.setText(label.getText() + buttons[i].getText());
               }
           }
        }

        for(int i = 8; i < 11; i++)
        {
           if(e.getSource() == buttons[i])
           {
               if(label.getText() == "0")
               {
                label.setText("");
                label.setText(label.getText() + buttons[i].getText());
               } else {
                label.setText(label.getText() + buttons[i].getText());
               }
           }
        }

        for(int i = 13; i < 14; i++)
        {
           if(e.getSource() == buttons[i])
           {
             if(label.getText() == "0")
             {
                label.setText("");
                label.setText(label.getText() + buttons[i].getText());
             } else {
                label.setText(label.getText() + buttons[i].getText());
             }
         }
     }

     // if statement that puts the labels text into the first or second number
     if(firstNumber)
     {
        number1 = Double.parseDouble(label.getText().trim());
     } else {
        number2 = Double.parseDouble(label.getText().trim());
     }

     // calculation
     if(e.getSource() == buttons[14])
     {
        // calculate
        if(devide){number1 = ((double)(number1) / (double)(number2)); }
        if(multiply){number1 = ((double)(number1) * (double)(number2)); }
        if(add){number1 = ((double)(number1) + (double)(number2)); }
        if(substract){number1 = ((double)(number1) - (double)(number2)); }
        label.setText(Double.toString(number1));
     }

 }

 public static void main(String[] args)
 {
    new Calculator();
 }
}

Lastly, the calculations made by the calculator are incorrect. I also can't wrap my head around what's causing that. Please bear in mind that I'm a beginner at Java and this is my first question on stackoverflow. Thanks in advance for helping me, whoever will :)

UPDATE: i fixed the errors by putting my code as follows:

if(e.getSource() == buttons[15])
    {
        // substract
        substract = true;

        add = false;
        devide = false;
        multiply = false;

        firstNumber = false;
        isNumberKey = false;

        if(isNumberKey)
        {
            if(firstNumber)
            {
                label.setText(label.getText().replace("/",""));
                label.setText(label.getText().replace("*",""));
                label.setText(label.getText().replace("+",""));
                label.setText(label.getText().replace("-",""));
                number1 = Double.parseDouble(label.getText().trim());
            } else {
                label.setText(label.getText().replace("/",""));
                label.setText(label.getText().replace("*",""));
                label.setText(label.getText().replace("+",""));
                label.setText(label.getText().replace("-",""));
                number2 = Double.parseDouble(label.getText().trim());
            }
        }

        Clear();

        label.setText("-");
    }

All i need to do now is fix the calculations... Thanks for the help everyone!

T0aster
  • 15
  • 1
  • 6
  • 2
    Welcome to SO! Whenever you bump into uncaught exceptions you will find the stacktrace with valuable information about which line the exception were thrown. Add this exception to the question by editing it. Also, point out exactly which line it is, since we don't have the line numbers. – Magnilex Nov 27 '14 at 14:49
  • @Magnilex Thanks! by stacktrace do you mean the list of errors? should i edit my post or my code? I'll add lines in a sec. – T0aster Nov 27 '14 at 14:55
  • The stacktrace shows the call chain that led to this particular exception. It is not really a list of errors. You should edit your question with this information. Also, it is better to just ask one specific question. The calculation errors are probably not related to this. – Magnilex Nov 27 '14 at 15:00
  • @Magnilex Thanks for explaining, i'll try fixing my errors according to the stacktrace. I am aware of the fact that im asking multiple questions in one post so sorry about that. I'll edit my post. – T0aster Nov 27 '14 at 15:21
  • String comparison is done as `s.equals("0")`. – Joop Eggen Nov 27 '14 at 16:25

2 Answers2

0

Disclaimer: I'm on my phone so it's hard to parse your code; with that being said, I believe your number format exception deals with what is stored in the label text.

From the looks of it if you hit an operator button (like multiply), the labelText will be "*", then if you hit number button (like 5), the labelText will be "*5". Finally, if you hit the enter button now to go calculate the answer, Double.parseDouble(label.getText().trim()), will be ran which will throw the NumberFormatException. Using the operation flags, it looks like you don't even need to store the operator (unless you're trying to display the operator to the user); in that case you need to strip the operator from the string before trying the parse the double.

label.setText(label.getText().replace("/",""));
label.setText(label.getText().replace("*",""));
label.setText(label.getText().replace("+",""));
label.setText(label.getText().replace("-",""));

As for the other exceptions, in eclipse you can set a breakpoint to halt the program when a specific exception occurs. This will help you debug your code further.

more info on that here

Community
  • 1
  • 1
David.Jones
  • 1,413
  • 8
  • 16
  • Thanks for your response! Your description is correct, do you know any fancy tricks to remove the operators? All i can think of is .replace("/,*,-,+","") < not sure if this works. – T0aster Nov 27 '14 at 15:28
  • I added the code you edited, i now get the NumberFormatException: empty string http://gyazo.com/c8b19902af9fc95e6690b9ee6ec6759c – T0aster Nov 27 '14 at 15:41
  • You are now trying to run Double.parseDouble(""), essentially. This is probably happening after you call the Clear() function, and then try to parse the label (the label is empty). A quick fix is to check if the label is empty before parsing it: `if(!label.getText().equals("")) ...` – David.Jones Nov 27 '14 at 15:51
  • Exactly :p i was reading my code through over and over and then i saw what you just mentioned. Thanks for confirming. I'm getting closer and closer to a final solution. – T0aster Nov 27 '14 at 16:05
  • Gah, i want to accept your answer as solution but it was a combination of 2 answers that lead to the actual solution... I put an update in my question with the fixed code so you still get some credit ;p Thanks again! – T0aster Nov 27 '14 at 16:23
0

Cannot delve totaly into your logic there, but here's some hints:

First, you don't have to guess where the error is. In case of uncaught exception like here, thread that produced it will print it's stack trace to console. It looks like this:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "/"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1222)
at java.lang.Double.parseDouble(Double.java:510)
at mypackage.Calculator.actionPerformed(Calculator.java:229)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6297)

From here you see that exception happened in thread named AWT-EventQueue-0, which is swing's standard event dispatching thread (all GUI applications handles events in single thread). Another thing you search in stack trace is to find what line in your code thrown it. Here it's the line:

at mypackage.Calculator.actionPerformed(Calculator.java:229)

In source, it is line:

number2 = Double.parseDouble(label.getText().trim());

, so you guessed right. What you can do is add another boolean there which will be set only if number button is hit, and then change that part of code to something like:

if( isNumber){
  if(firstNumber)
    {
        number1 =     Double.parseDouble(label.getText().trim());
    } else {
        number2 = Double.parseDouble(label.getText().trim());
    }
}

Apart from that, instead of using multiple boolean flags for operation, use Java enum type

enum Operation {devide, substract, add, multiply};

your code will be more readable and "java" styled. Good starting point, just go ahead!

Vuk Djapic
  • 816
  • 13
  • 29
  • Thanks alot for the explanation! i just realised what my code was actually doing... >< I'm not known with enum's in java yet so im probably not using that for now, but thanks for the suggestion, I'll look into it. – T0aster Nov 27 '14 at 15:48