4

I have made this calculator program in Java. This works well only when two numbers are calculated at one time. That means to get the sum of 1+2+3 you have to go this way : press 1 press + press 2 press = press + press 3 press =

and it calculates it as 6.

But I want to program this so that I can get the answer by: press 1 press + press 2 press + press 3 press =

but this gives the answer 5!!! How to code this so that it works like an ordinary calculator?

Here is my code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class cal1 extends JFrame {

double op1 = 0d, op2 = 0d;
double result = 0d;
char action;
boolean b = false;
boolean pressequal = false;

public cal1() {
    makeUI();
}

private void makeUI() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(400, 400);

    b0 = new JButton("0");
    b1 = new JButton("1");
    b2 = new JButton("2");
    b3 = new JButton("3");
    b4 = new JButton("4");
    b5 = new JButton("5");
    b6 = new JButton("6");
    b7 = new JButton("7");
    b8 = new JButton("8");
    b9 = new JButton("9");
    bDot = new JButton(".");
    bMul = new JButton("*");
    bDiv = new JButton("/");
    bPlus = new JButton("+");
    bMinus = new JButton("-");
    bEq = new JButton("=");

    t = new JTextField(12);
    t.setFont(new Font("Tahoma", Font.PLAIN, 24));
    t.setHorizontalAlignment(JTextField.RIGHT);

    numpad = new JPanel();
    display = new JPanel();

    numpad.add(b7);
    numpad.add(b8);
    numpad.add(b9);
    numpad.add(bMul);
    numpad.add(b4);
    numpad.add(b5);
    numpad.add(b6);
    numpad.add(bDiv);
    numpad.add(b1);
    numpad.add(b2);
    numpad.add(b3);
    numpad.add(bMinus);
    numpad.add(bDot);
    numpad.add(b0);
    numpad.add(bEq);
    numpad.add(bPlus);

    numpad.setLayout(new GridLayout(4, 5, 5, 4));

    display.add(t);
    add(display, BorderLayout.NORTH);
    add(numpad, BorderLayout.CENTER);

    t.addKeyListener(new KeyAdapter() {
        @Override
        public void keyTyped(KeyEvent e) {
            typeOnt(e);
        }
    });

    b0.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b0pressed(e);
        }
    });

    b1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b1pressed(e);
        }
    });

    b2.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b2pressed(e);
        }
    });

    b3.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b3pressed(e);
        }
    });

    b4.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b4pressed(e);
        }
    });

    b5.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b5pressed(e);
        }
    });

    b6.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b6pressed(e);
        }
    });

    b7.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b7pressed(e);
        }
    });

    b8.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b8pressed(e);
        }
    });

    b9.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            b9pressed(e);
        }
    });

    bDot.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bDotpressed(e);
        }
    });

    bPlus.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bPlusPressed(e);
        }
    });

    bMinus.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bMinusPressed(e);
        }
    });

    bMul.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bMulPressed(e);
        }
    });

    bDiv.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bDivPressed(e);
        }
    });

    bEq.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            bEqpressed(e);
        }
    });

}

void typeOnt(KeyEvent e) {
    e.consume();
}

void b0pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "0");
    } else {
        t.setText(t.getText() + "0");
    }
}

void b1pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "1");
    } else {
        t.setText(t.getText() + "1");
    }
}

void b2pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "2");
    } else {
        t.setText(t.getText() + "2");
    }
}

void b3pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "3");
    } else {
        t.setText(t.getText() + "3");
    }
}

void b4pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "4");
    } else {
        t.setText(t.getText() + "4");
    }
}

void b5pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "5");
    } else {
        t.setText(t.getText() + "5");
    }
}

void b6pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "6");
    } else {
        t.setText(t.getText() + "6");
    }
}

void b7pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "7");
    } else {
        t.setText(t.getText() + "7");
    }
}

void b8pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "8");
    } else {
        t.setText(t.getText() + "8");
    }
}

void b9pressed(ActionEvent e) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + "9");
    } else {
        t.setText(t.getText() + "9");
    }
}

void bDotpressed(ActionEvent e) {
    if (!t.getText().contains(".")) {
        if (b) {
            t.setText(null);
            b = false;
            t.setText(t.getText() + "0.");
        } else if (t.getText().isEmpty()) {
            t.setText("0.");
        } else {
            t.setText(t.getText() + ".");
        }
    }
}

void bPlusPressed(ActionEvent e) {
    b = true;
    action = '+';
    op1 = Double.parseDouble(t.getText());

}

void bMinusPressed(ActionEvent e) {
    b = true;
    action = '-';
    op1 = Double.parseDouble(t.getText());
}

void bMulPressed(ActionEvent e) {
    b = true;
    action = '*';
    op1 = Double.parseDouble(t.getText());
}

void bDivPressed(ActionEvent e) {
    b = true;
    action = '/';
    op1 = Double.parseDouble(t.getText());
}

void bEqpressed(ActionEvent e) {
    op2 = Double.parseDouble(t.getText());
    doCal();
}

void doCal() {
    switch (action) {
        case '+': result = op1 + op2; break;
        case '-': result = op1 - op2; break;
        case '*': result = op1 * op2; break;
        case '/': result = op1 / op2; break;
    }      
    t.setText(String.valueOf(result));
}

public static void main(String[] args) {
    new cal1().setVisible(true);
}

JButton b0;
JButton b1;
JButton b2;
JButton b3;
JButton b4;
JButton b5;
JButton b6;
JButton b7;
JButton b8;
JButton b9;
JButton bDot;
JButton bPlus;
JButton bMinus;
JButton bMul;
JButton bDiv;
JButton bEq;
JPanel display;
JPanel numpad;
JTextField t;
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Peter1
  • 157
  • 1
  • 2
  • 13
  • What does your analysis say? how should this be made to work? – ajay.patel Jun 30 '13 at 19:16
  • 2
    @hexafraction: not true. If they are asked in a suitable form (not just copy paste of the asignment) they are totally fine to be asked here. – Burkhard Jun 30 '13 at 19:17
  • 1
    Welcome to Stack Overflow! Debugging is a critical skill for all programmers. I strongly suggest that you learn how to use your IDEs built-in debugger. You can also add more System.out.println() statements to your code in order to see what is happening – Code-Apprentice Jun 30 '13 at 19:17
  • Also, you might consider using an array for the buttons with numbers. This can greatly reduce the amount of code for creating and using the buttons. – Code-Apprentice Jun 30 '13 at 19:18
  • I want this to work like an ordinary hand held calculator. Or like the ones comes with the operating system. This messes up calculations when I press * / - + = like crazy but other calculators don't. They just do the things perfect to the order I press them. – Peter1 Jun 30 '13 at 19:24
  • And by the way I think I should learn debugging first. Thanks for pointing that out Monad. – Peter1 Jun 30 '13 at 19:25
  • Use the [`ScriptEngine`](http://download.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html). E.G. [here](http://stackoverflow.com/questions/7441625/how-to-find-a-button-source-in-awt-calculator-homework/7441804#7441804). – Andrew Thompson Jul 01 '13 at 01:16

3 Answers3

4

First in Java classes should be start with first letter UpperCase Java Code Conventions

Second instead of creating a method for each number

void bpressed(ActionEvent e, Integer number) {
    if (b) {
        t.setText(null);
        b = false;
        t.setText(t.getText() + number);
    } else {
        t.setText(t.getText() + number);
    }
}

Use declarative names for things, what is b? it is not intuitive, class name should be Calculator or something like this, code must be readable for humans.

Related to your question you can have a partialResult when some operation is in progress. For example:

you declare

private double partialResult=0D;

and a method something like this

private void calculatePartialResult(Integer numberSelected){
      //choose depends on action
      partialResult op= numberSelected;  (where op in + - * /)    
  }
nachokk
  • 14,363
  • 4
  • 24
  • 53
3

Get the calculation as a string and use ScriptEngine:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
t.setText(engine.eval(calculation_String));
imulsion
  • 8,820
  • 20
  • 54
  • 84
  • good solution, but needs JS experiences :D, thanks I didn't know about it –  Jun 30 '13 at 19:36
  • I have no much experience in JS. But this worked fine. Thanks. Adding parantheses buttons made it better :) But I want to know what is the logic behind these calculations. – Peter1 Jun 30 '13 at 20:04
1

When doing 1 + 2 + 3 your current code is doing :

User tap on '1' '+' 
op1 = 1.0, action = '+' 

User tap on '2' '+'
op1 = 2.0, action = '+'

User tap on '3' '='
op1 = 2.0, op2 = 3.0, action = '+'

doCal() displays the result of op1 + op2 which is 5

I think that you should use op1 to store the value of the previous calculations to obtain the behavior you are expecting.

Here is how I would do it.

Instead of calling doCal() only when equal is pressed, call it every time an operator is pressed, at the start of the operator action handler. Store the value inside of op2, to allow the calculation to take place :

void bPlusPressed(ActionEvent e) {
    op2 = Double.parseDouble(t.getText());
    doCal();
    b = true;
    action = '+';
}

(Apply the same changes for the other operators).

Inside of doCal(), store the result into op1 instead of displaying it :

void doCal() {
    // No need to use a class attribute for result, prefer a local variable.
    final double result;
    switch (action) {
        case '+': result = op1 + op2; break;
        case '-': result = op1 - op2; break;
        case '*': result = op1 * op2; break;
        case '/': result = op1 / op2; break;
        // When no action is set, simply copy op2 into op1
        default: result = op2;
    }
    op1 = result;
}

Then, change bEqPressed() to make it display op1 and reset the value of action :

void bEqpressed(ActionEvent e) {
    op2 = Double.parseDouble(t.getText());
    doCal();
    t.setText(String.valueOf(result));
    action = '\0';
}

This should do the trick.

Raphaël
  • 3,646
  • 27
  • 28