user1959360
user1959360

Reputation: 29

Calculator program in java

I am a beginner in java and I have written this code with the help of an online available program. The code attached is a part of the code which performs action when buttons of the calculator are pressed.In the CalculatorDemo class i have initialized all the buttons(b0-b24) and the TextField tf. In this class I am using char OP as a flag ,so that, when I press '+' the OP is assigned '+' and I have even checked it on command prompt. But when i press '=' ,the OP is automatically assigned '\0' and i don't know how and why. And hence, no operation is performed at all. And I don't understand where the logic is wrong. Please help

    import java.awt.event.*;
    import java.awt.*;

class CalculatorActionperform implements ActionListener
{
    CalculatorDemo temp;
    public boolean foundKey;
    String command;
    String s="", s1,s2,s3,s4,s5,s6;
     int  n; 
     char OP;

CalculatorActionperform(CalculatorDemo d)
    {
temp=d;


    }

public void actionPerformed(ActionEvent e)
        {

        if(e.getSource()==temp.b23)
            {
            s3=temp.tf.getText();
            s4="0";
            s5=s3+s4;
            temp.tf.setText(s5); 
            }
        if(e.getSource()==temp.b22)
            {
            s3=temp.tf.getText();
            s4="1";
            s5=s3+s4;
            temp.tf.setText(s5); 
            }
        if(e.getSource()==temp.b21)
            {
            s3=temp.tf.getText();
            s4="2";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b20)
            {
            s3=temp.tf.getText();
            s4="3";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b15)
            {
            s3=temp.tf.getText();
            s4="4";
            s5=s3+s4;
            temp.tf.setText(s5); 
            }
        if(e.getSource()==temp.b16)
            {
            s3=temp.tf.getText();
            s4="5";
            s5=s3+s4;
            temp.tf.setText(s5); 
            }
        if(e.getSource()==temp.b17)
            {
            s3=temp.tf.getText();
            s4="6";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b12)
            {
            s3=temp.tf.getText();
            s4="7";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b11)
            {
            s3=temp.tf.getText();
            s4="8";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b10)
            {
            s3=temp.tf.getText();
            s4="9";
            s5=s3+s4;
            temp.tf.setText(s5);
            }
        if(e.getSource()==temp.b14)
            {
            s1=temp.tf.getText();
            temp.tf.setText("");
            OP='+';

            }
        if(e.getSource()==temp.b19)
            {
            s1=temp.tf.getText();
            temp.tf.setText("");
            OP='-';
            }
        if(e.getSource()==temp.b18)
            {
            s1=temp.tf.getText();
            temp.tf.setText("");
            OP='*';
            }
        if(e.getSource()==temp.b13)
            {
            s1=temp.tf.getText();
            temp.tf.setText("");
            OP='/';
            }
        if(e.getSource()==temp.b9)   /* b9= '=' */
            {
            s2=temp.tf.getText();


            if(OP=='\0')
                {
                System.out.println("null");
                }
            if(OP=='+')
            {
            n=Integer.parseInt(s1)+Integer.parseInt(s2);
            temp.tf.setText(String.valueOf(n));
            }
                    else
                        if(OP=='-')
                            {
                            n=Integer.parseInt(s1)-Integer.parseInt(s2);
                            temp.tf.setText(String.valueOf(n));
                            }
                    else 
                        if(OP=='*')
                            {
                            n=Integer.parseInt(s1)*Integer.parseInt(s2); 
                            temp.tf.setText(String.valueOf(n)); 
                            }
                    else 

                    if(OP=='/')
                            {
                            n=Integer.parseInt(s1)/Integer.parseInt(s2); 
                            temp.tf.setText(String.valueOf(n));
                            }
                                }


            if(e.getSource()==temp.b6)
                {
                temp.tf.setText("");
                }
        }
    }

Upvotes: 2

Views: 22001

Answers (4)

user4458695
user4458695

Reputation: 29

import java.util.Scanner;
public class Calculator {

public static void main(String[] args) {

    Scanner input = new Scanner(System.in);

    Math. = new Maths();

    double answer = 0;
    double inputA, inputB;
    char operator;
    boolean done = false;

     while (done == false) {
        System.out.print("Please enter your sum: ");

        inputA = input.nextDouble();
        operator = input.next().charAt(0);
        inputB = input.nextDouble();        

        switch (operator) {
            case '+': answer = Math.add(inputA, inputB);
                      break;
            case '-': answer = Math.subtract(inputA, inputB);
                      break;
            case '*': answer = Math.multiply(inputA, inputB);
                      break;
            case '/': answer = Math.divide(inputA, inputB);
                      break;
            case '^': answer = Math.power(inputA, inputB);
                      break;
        }

            System.out.println(answer);             
    }       

    input.close();

  }

}

Upvotes: 0

Bhumi Patel
Bhumi Patel

Reputation: 21

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class calculatatorApp extends Applet implements ActionListener {



            Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ad,sub,mul,div,mo,eq,c;
            TextField t1;
            static int a=0,b=0,res=0;
                public calculatatorApp()
                {   


                    Panel p1=new Panel();
                    Panel p2=new Panel();


                    t1=new TextField(10);
                    b0=new Button("0");
                    b1=new Button("1");
                    b2=new Button("2");
                    b3=new Button("3");
                    b4=new Button("4");
                    b5=new Button("5");
                    b6=new Button("6");
                    b7=new Button("7");
                    b8=new Button("8");
                    b9=new Button("9");
                    ad=new Button("+");
                    sub=new Button("-");
                    mul=new Button("*");
                    div=new Button("/");
                    mo=new Button("%");
                    eq=new Button("=");
                    c=new Button("c");



                    c.addActionListener(this);
                    b0.addActionListener(this);
                    b1.addActionListener(this);
                    b2.addActionListener(this);
                    b3.addActionListener(this);
                    b4.addActionListener(this);
                    b5.addActionListener(this);
                    b6.addActionListener(this);
                    b7.addActionListener(this);
                    b8.addActionListener(this);
                    b9.addActionListener(this);
                    ad.addActionListener(this);
                    sub.addActionListener(this);
                    mul.addActionListener(this);
                    div.addActionListener(this);
                    mo.addActionListener(this);
                    eq.addActionListener(this);









                    p1.add(t1);
                    p2.add(b1);
                    p2.add(b2);
                    p2.add(b3);
                    p2.add(ad);
                    p2.add(b4);
                    p2.add(b5);
                    p2.add(b6);
                    p2.add(sub);
                    p2.add(b7);
                    p2.add(b8);
                    p2.add(b9);
                    p2.add(mul);
                    p2.add(b0);
                    p2.add(c);
                    p2.add(eq);
                    p2.add(mo);
                    p2.add(div);







                }

                @Override
                public void actionPerformed(ActionEvent ae) {
                    // TODO Auto-generated method stub




                    String str=ae.getActionCommand();
                    if(str.equals("0"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("1"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("2"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("3"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("4"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("5"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("6"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("7"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("8"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }
                    if(str.equals("9"))
                    {
                        t1.setText(t1.getText()+""+str);

                    }

                    if(t1.getText().equals("0"))
                    {
                        t1.setText("");


                    }   
                    if(str.equals("+")|| str.equals("-")||str.equals("*")||str.equals("/")||str.equals("%") )
                        {
                        a=Integer.parseInt(t1.getText());
                        t1.setText("");
                    }
                        if(str.equals("=")){
                            b=Integer.parseInt(t1.getText());

                        res=a+b;
                        t1.setText(""+res);
                        res=a-b;
                        t1.setText(""+res);
                        res=a*b;
                        t1.setText(""+res);
                        res=a/b;
                        t1.setText(""+res);
                        res=a%b;
                        t1.setText(""+res);


                        }



                }
}                   

Upvotes: 0

Bhumi Patel
Bhumi Patel

Reputation: 21

class InvalidNum2 extends Exception
{
    InvalidNum2()
    {   
    super("Invalid Num:num2 cannot be zero");
    }


}
class Calculator
{
static int div(int n,int m) throws InvalidNum2
    {
        if(m==0)
        {
            throw new InvalidNum2();
        }
        else
        {
            return(n/m);
        }
    }
     public static void main(String args[])
    {

        int num1,num2;
        int a,b,c,d;



        num1=Integer.parseInt(args[0]);
        num2=Integer.parseInt(args[2]);
        char op=args[1].charAt(0);

                if(args.length!=3)
        {
            System.out.println("incorrect no. of argument");
                System.exit(0);
        }
               else
                {
           try
           {
                    switch(op)
            {
                case '+' :
                                          a=num1+num2;
                      System.out.println("additiom:"+a);
                      break;
                case '-' :
                      b=num1-num2;
                      System.out.println("Sub:"+b);
                      break;
                case '*' :
                      c=num1*num2;
                      System.out.println("mul:"+c);
                      break;
                case '/' :
                       d=div(num1,num2);
                       System.out.println("div:"+d);
                       break;
                               default :
                                       { System.out.println("wrong ch");}
            }
            }catch(Exception E){
System.out.println(E);}
        }

    }
}

Upvotes: 0

Mike Tunnicliffe
Mike Tunnicliffe

Reputation: 10772

I'm not going to go into the code you have posted in your questions, but rather attempt to help you attack your overall goal of writing a calculator demo.

The first step should be to get a clear idea of the problem by writing it down:

I need a calculator with a display and a keypad with the digits 0-9 and the operators +,-,x,/ and an = button. The calculator should read a series digits from the keypad, then a mathematical operator, then another series of digits and so on. Each uninterrupted series of digits should be converted into an integer value.

The calculator should calculate the result of applying the mathematical operator to the first and second integer values. If further operators and integers are entered, the mathematical operator should be applied to the result of the prior calculation and the further integer. This process should continue until the equals button is pressed. When digits are pressed on the keypad they should appear in the text display appended to those digits entered so far.

When an operator or the equals button is pressed this signals the end of the entry of an integer, if this completes a calculation then the result should be shown on the display, otherwise the integer should remain in the display until another digit is pressed - then the display should be cleared and the new digit displayed, and subsequent digits appended, as before.

From this description we can identify some nouns: Calculator, Button, Display, Keypad, Digit, Operator, Integer, Result ...and some verbs: Read, Press, Convert, Calculate, Apply, Enter, Complete, Show, Remain, Clear, Display, Append

These give us an idea of the state and behaviour required for our program. We then decide how to model these in our implementation. Typically nouns can be modelled as classes/instance variables (state) and verbs as methods (behaviour).

Here is one possible design:

A class called Calculator using Swing components to represent the Buttons/Keypad and Display; using the primitive int type for representing Integer/Result/Digit; using Java mathematical operators for representing Operator.

Let's start to make the bones of this:

public class Calculator {
    private JFrame window;
    private List<JButton> keypad;
    private JLabel display;
    private int result;
    private StringBuffer digitsEntered;
    private int integerEntered;
}

Now we need to work out how we are going to Read/Press buttons. We will need to set up our JButtons to respond to being activated and wire up that event to a method we define in our Calculator class.

One way to do this is to create the JButtons and add a listener to them. We can make Calculator implement the ActionListener interface, which forces it to define a method actionPerformed with a single ActionEvent argument. We can see how this would work by creating a JButton in Calculator's constructor.

public class Calculator implements ActionListener {
    private JFrame window;
    private List<JButton> keypad;
    private JLabel display;
    private int result;
    private StringBuffer digitsEntered;
    private int integerEntered;

    public Calculator() {
        JButton zeroButton = new JButton("0");
        zeroButton.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        // this would get executed when zeroButton is pressed
    }
}

Note this code won't do anything yet because we haven't set up the window and connected the button to it. However, the code should illustrate how we can run code from a button press.

Let's get on and get this code in a working state by setting everything up:

public class Calculator implements ActionListener {
    private JFrame window;
    private List<JButton> keypad;
    private JLabel display;
    private int result;
    private StringBuffer digitsEntered;
    private int integerEntered;

    public Calculator() {
        window = new JFrame("Calculator");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton zeroButton = new JButton("0");
        zeroButton.addActionListener(this);
        window.add(zeroButton, BorderLayout.CENTER);

        window.pack();
        window.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // this would get executed when zeroButton is pressed
        JOptionPane.showMessageDialog(window, "Button pressed");
    }

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

OK, we need more than one button, we need a whole load. Let's make digits 0-9:

for (int digit = 0; digit <=9; digit++) {
    JButton button = new JButton(Integer.toString(digit));
    button.addActionListener(this);
    window.add(button);
}

Hmm that didn't work right - only one button appears on the window. That's because we have the default window layout which isn't what we need. We want the buttons to appear in a grid, grouped together in the window. Let's create a JPanel to group the buttons together in and use a GridLayout for the panel, then we can add the panel to the window.

    public Calculator() {
        window = new JFrame("Calculator");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel digitsPanel = new JPanel();
        digitsPanel.setLayout(new GridLayout(4, 3));
        for (int digit = 0; digit <=9; digit++) {
            JButton button = new JButton(Integer.toString(digit));
            button.addActionListener(this);
            digitsPanel.add(button);
        }
        window.add(digitsPanel);

        window.pack();
        window.setVisible(true);
    }

That's not bad, but the numbers don't come up in the usual order you'd see on a numpad. That's because they appear in the order added from top-left to bottom-right. We can fix that by specifying the order we want with an array, and iterate through that (we use the for-each style iterator for this because it's neater). While we're doing that, we can do something similar for the mathematical operators and equals button and add them to the frame too (here we'll be explicit about the layout to use for the window and we'll use a BorderLayout).

    public Calculator() {
        window = new JFrame("Calculator");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setLayout(new BorderLayout());

        JPanel digitsPanel = new JPanel();
        digitsPanel.setLayout(new GridLayout(4, 3));
        int[] digitOrder = new int[] { 7,8,9,4,5,6,1,2,3,0 };
        for (int digit : digitOrder) {
            JButton button = new JButton(Integer.toString(digit));
            button.addActionListener(this);
            digitsPanel.add(button);
        }
        window.add(digitsPanel, BorderLayout.CENTER);

        JPanel operatorsPanel = new JPanel();
        operatorsPanel.setLayout(new GridLayout(5,1));
        String[] operators = new String[] { "+","-","x","/","=" };
        for (String operator : operators) {
            JButton button = new JButton(operator);
            button.addActionListener(this);
            operatorsPanel.add(button);
        }
        window.add(operatorsPanel, BorderLayout.EAST);

        window.pack();
        window.setVisible(true);
    }

OK, we're nearly done with the components. We just need to add a display.

    ...
    private JLabel display;
    ...
    public Calculator() {
        window = new JFrame("Calculator");
        ...
        display = new JLabel();
        display.setHorizontalAlignment(JLabel.RIGHT);
        display.setText("0");
        window.add(display, BorderLayout.NORTH);
        ...
        window.pack();
        window.setVisible(true);
    }

Now we just need to implement the logic to respond to button presses. First, let's see what we need to do if a digit is pressed. We need to deal with the Append and Show verbs and append that digit to our input and display it.

    StringBuffer digitsEntered;
    ...
    public Calculator() {
        ...
        digitsEntered = new StringBuffer();
        ...
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            String buttonText = ((JButton)e.getSource()).getText();
            if (Character.isDigit(buttonText.charAt(0))) {
                digitsEntered.append(buttonText.charAt(0));
                display.setText(digitsEntered.toString());
            }
        }
    }

Cool. Now we need to implement the Convert verb and convert our digits into an integer. This will happen when an operator or equals is pressed. We need to remember what operator was pressed so we know what calculation to do when the second integer is entered.

    private String currentOperator;
    ...
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            String buttonText = ((JButton)e.getSource()).getText();
            if (Character.isDigit(buttonText.charAt(0))) {
                digitsEntered.append(buttonText.charAt(0));
                display.setText(digitsEntered.toString());

            } else {
                integerEntered = Integer.parseInt(digitsEntered.toString());
                digitsEntered.setLength(0); // clear out the input so a new integer can be entered
                currentOperator = buttonText; // remember the operator
            }
        }
    }

Now we actually need to handle the second time an operator or equals is pressed, when we already have an integer and operator saved away. Here we can implement the + part of the Calculate/Apply verb and Show the result.

            ...
            } else {
                if (currentOperator == null) {
                    integerEntered = Integer.parseInt(digitsEntered.toString());
                } else {
                    int previousInteger = integerEntered;
                    integerEntered = Integer.parseInt(digitsEntered.toString());

                    if ("+".equals(currentOperator)) {
                        result = previousInteger + integerEntered;
                        display.setText(Integer.toString(result));
                    }
                }
                digitsEntered.setLength(0); // clear out the input so a new integer can be entered
                currentOperator = buttonText; // remember the operator
            }
            ...

This isn't quite right. It will put into result the sum of the previous 2 integers rather than the sum of all integers entered so far. We need to store the first value in result then add each subsequent integer to the value stored in result. This means we don't need the previousInteger variable any more, and we have some duplicate code in both the if and else that we can just execute before the if.

                ...
                integerEntered = Integer.parseInt(digitsEntered.toString());
                if (currentOperator == null) {
                    result = integerEntered;
                } else {
                    if ("+".equals(currentOperator)) {
                        result = result + integerEntered;
                        display.setText(Integer.toString(result));
                    }
                }
                ...

Let's implement the other operators.

                ...
                integerEntered = Integer.parseInt(digitsEntered.toString());
                if (currentOperator == null) {
                    result = integerEntered;
                } else {
                    if ("+".equals(currentOperator)) {
                        result = result + integerEntered;
                    } else if ("-".equals(currentOperator)) {
                        result = result - integerEntered;
                    } else if ("x".equals(currentOperator)) {
                        result = result * integerEntered;
                    } else if ("/".equals(currentOperator)) {
                        result = result / integerEntered;
                    } else if ("=".equals(currentOperator)) {
                        result = integerEntered;
                    } else {
                        // Unrecognised operator
                    }
                    display.setText(Integer.toString(result));
                }
                ...

Here we make = an operator that acts like a reset and allow us to start a new calculation. You may notice you get an error if you try to hit = then + (to add a number to the result); this is because there are no digits in the input to convert to an integer for the + operator. We can solve this by skipping the calculation in this case.

                ...
                if (digitsEntered.length() > 0) { 
                    integerEntered = Integer.parseInt(digitsEntered.toString());
                    if (currentOperator == null) {
                        result = integerEntered;
                    } else {
                        if ("+".equals(currentOperator)) {
                            result = result + integerEntered;
                        } else if ("-".equals(currentOperator)) {
                            result = result - integerEntered;
                        } else if ("x".equals(currentOperator)) {
                            result = result * integerEntered;
                        } else if ("/".equals(currentOperator)) {
                            result = result / integerEntered;
                        } else if ("=".equals(currentOperator)) {
                            result = integerEntered;
                        } else {
                            // Unrecognised operator
                        }
                        display.setText(Integer.toString(result));
                    }
                }
                ...

Here is the full code so far. It doesn't handle divide by 0, keypad is never used and can be removed, and integerEntered really need only be a local variable and not a instance variable. However, the code should mostly work, let me know if you spot any problems. I also have a cleaner version (the first implementation I did) but it wasn't so simple to explain.

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class Calculator implements ActionListener {
    private JFrame window;
    private List<JButton> keypad;
    private JLabel display;
    private int result;
    private StringBuffer digitsEntered;
    private int integerEntered;
    private String currentOperator;

    public Calculator() {
        window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setLayout(new BorderLayout());

        digitsEntered = new StringBuffer();

        display = new JLabel();
        display.setHorizontalAlignment(JLabel.RIGHT);
        display.setText("0");
        window.add(display, BorderLayout.NORTH);

        JPanel digitsPanel = new JPanel();
        digitsPanel.setLayout(new GridLayout(4, 3));
        int[] digitOrder = new int[] { 7,8,9,4,5,6,1,2,3,0 };
        for (int digit : digitOrder) {
            JButton button = new JButton(Integer.toString(digit));
            button.addActionListener(this);
            digitsPanel.add(button);
        }
        window.add(digitsPanel, BorderLayout.CENTER);

        JPanel operatorsPanel = new JPanel();
        operatorsPanel.setLayout(new GridLayout(5,1));
        String[] operators = new String[] { "+","-","x","/","=" };
        for (String operator : operators) {
            JButton button = new JButton(operator);
            button.addActionListener(this);
            operatorsPanel.add(button);
        }
        window.add(operatorsPanel, BorderLayout.EAST);

        window.pack();
        window.setVisible(true);
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            String buttonText = ((JButton)e.getSource()).getText();
            if (Character.isDigit(buttonText.charAt(0))) {
                digitsEntered.append(buttonText.charAt(0));
                display.setText(digitsEntered.toString());
            } else {
                if (digitsEntered.length() > 0) { 
                    integerEntered = Integer.parseInt(digitsEntered.toString());
                    if (currentOperator == null) {
                        result = integerEntered;
                    } else {
                        if ("+".equals(currentOperator)) {
                            result = result + integerEntered;
                        } else if ("-".equals(currentOperator)) {
                            result = result - integerEntered;
                        } else if ("x".equals(currentOperator)) {
                            result = result * integerEntered;
                        } else if ("/".equals(currentOperator)) {
                            result = result / integerEntered;
                        } else if ("=".equals(currentOperator)) {
                            result = integerEntered;
                        } else {
                            // Unrecognised operator
                        }
                        display.setText(Integer.toString(result));
                    }
                }
                digitsEntered.setLength(0); // clear out the input so a new integer can be entered
                currentOperator = buttonText; // remember the operator
            }
        }
    }

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

Here's the cleaner, but more complicated version:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class CalculatorDemo extends JFrame  {
    private static final long serialVersionUID = 1L;

    private StringBuffer inputBuffer = new StringBuffer();
    private String queuedOperator = null;
    private int leftHandSide = 0;
    private JLabel inputDisplay;
    private JLabel operatorIndicator;

    private class DigitButtonAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        private final int digit;
        public DigitButtonAction(final int digit) {
            super(Integer.toString(digit));
            this.digit = digit;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            enterDigit(digit);
        }
    }
    private class OperatorButtonAction extends AbstractAction {
        private static final long serialVersionUID = 1L;
        private final String operator;
        public OperatorButtonAction(final String operator) {
            super(operator);
            this.operator = operator;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            performOperation(operator);
        }
    }

    public CalculatorDemo() {
        super("Calculator");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setSize(100, 200);

        // Create display text field
        inputDisplay = new JLabel();
        inputDisplay.setHorizontalAlignment(JLabel.RIGHT);
        inputDisplay.setText(Integer.toString(leftHandSide));

        operatorIndicator = new JLabel();
        operatorIndicator.setBorder(new EmptyBorder(0, 4, 0, 4));

        final JPanel display = new JPanel();
        display.setLayout(new BorderLayout());
        display.add(inputDisplay, BorderLayout.CENTER);
        display.add(operatorIndicator, BorderLayout.WEST);

        // Create number buttons
        final JPanel digitPanel = new JPanel();
        digitPanel.setLayout(new GridLayout(4,3));
        final int[] digitKeyOrder = new int[] { 7,8,9,4,5,6,1,2,3 };
        for (int digit : digitKeyOrder) {
            digitPanel.add(new JButton(new DigitButtonAction(digit)));
        }
        digitPanel.add(new JPanel()); // Blank spacer panel
        digitPanel.add(new JButton(new DigitButtonAction(0)));

        // Create operators
        final String[] OPERATORS = { "+","-","*","/","=" };
        final JPanel operatorPanel = new JPanel();
        operatorPanel.setLayout(new GridLayout(OPERATORS.length, 1));
        for (String op : OPERATORS) {
            operatorPanel.add(new JButton(new OperatorButtonAction(op)));
        }

        add(digitPanel, BorderLayout.CENTER);
        add(operatorPanel, BorderLayout.EAST);
        add(display, BorderLayout.NORTH);

        pack();
    }

    private void enterDigit(final int digit) {
        if (digit == 0 && inputBuffer.length() == 0) return;
        inputBuffer.append(Integer.toString(digit));
        inputDisplay.setText(inputBuffer.toString());
    }

    private int calculate(final int leftHandSide, final String operator, final int rightHandSide) {
        if (operator == null) return rightHandSide;
        else if ("+".equals(operator)) return leftHandSide + rightHandSide;
        else if ("-".equals(operator)) return leftHandSide - rightHandSide;
        else if ("*".equals(operator)) return leftHandSide * rightHandSide;
        else if ("/".equals(operator)) return leftHandSide / rightHandSide;
        else if ("=".equals(operator)) return rightHandSide;
        else {
            throw new IllegalStateException("Unrecognised operator " + operator);
        }
    }

    private void performOperation(final String operator) {
        try {
            final int rightHandSide = Integer.parseInt(inputBuffer.toString());
            leftHandSide = calculate(leftHandSide, queuedOperator, rightHandSide);
        } catch (NumberFormatException e) {
            // Ignore failure to parse inputBuffer to integer
            // calculate() not called, just carry on and clear the
            // inputBuffer and queue a new operator
        } catch (ArithmeticException e) {
            // Divide by 0 in calculate()
            operatorIndicator.setText("");
            inputDisplay.setText(e.getMessage());
            queuedOperator = null;
            return;
        } catch (IllegalStateException e) {
            // Unrecognised operator
            operatorIndicator.setText("");
            inputDisplay.setText(e.getMessage());
            queuedOperator = null;
            return;
        }
        inputBuffer.setLength(0); // Clear inputBuffer
        queuedOperator = operator; // Queue next operator
        // Update display
        operatorIndicator.setText(queuedOperator);
        inputDisplay.setText(Integer.toString(leftHandSide));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new CalculatorDemo().setVisible(true);
            }
        });
    }
}

Upvotes: 10

Related Questions