I have been trying to create a (ugly) calculator and I am having problems with "=" sign. I know how to convert numbers (in string) to numbers (in int), but the problem here is mainly */-+. I have absolutely no idea what to do when they are added to the situation.
Here is a gif of the calculator: http://gyazo.com/98781eaaca0b3152967e6370cad3df15
package megetenkelkalkis;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.text.DecimalFormat;
import javax.swing.*;
class Kalkulator extends JFrame{
private String textfield = "";
private String replace ="";
private JButton btn0 = new JButton("0");
private JButton btn1 = new JButton("1");
private JButton btn2 = new JButton("2");
private JButton btn3 = new JButton("3");
private JButton btn4 = new JButton("4");
private JButton btn5 = new JButton("5");
private JButton btn6 = new JButton("6");
private JButton btn7 = new JButton("7");
private JButton btn8 = new JButton("8");
private JButton btn9 = new JButton("9");
private JButton btnlik = new JButton("=");
private JButton btngange = new JButton("*");
private JButton btndele = new JButton("/");
private JButton btnpluss = new JButton("+");
private JButton btnminus = new JButton("-");
private JTextField tekst = new JTextField();
private JButton btndel= new JButton("DEL");
JPanel p = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
public Kalkulator(String tittel){
tekst.setPreferredSize(new Dimension(310,25));
setTitle(tittel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.add(btn0);
p.add(btn1);
p.add(btn2);
p.add(btn3);
p.add(btn4);
p.add(btn5);
p.add(btnlik);
p2.add(btn6);
p2.add(btn7);
p2.add(btn8);
p2.add(btn9);
p2.add(btndele);
p2.add(btngange);
p2.add(btnpluss);
p2.add(btnminus);
p3.add(tekst);
p3.add(btndel);
add(p, BorderLayout.SOUTH);
add(p2, BorderLayout.CENTER);
add(p3, BorderLayout.NORTH);
pack();
Knappelytter knappelytteren = new Knappelytter();
btn0.addActionListener(knappelytteren);
btn1.addActionListener(knappelytteren);
btn2.addActionListener(knappelytteren);
btn3.addActionListener(knappelytteren);
btn4.addActionListener(knappelytteren);
btn5.addActionListener(knappelytteren);
btn6.addActionListener(knappelytteren);
btn7.addActionListener(knappelytteren);
btn8.addActionListener(knappelytteren);
btn9.addActionListener(knappelytteren);
btnlik.addActionListener(knappelytteren);
btndele.addActionListener(knappelytteren);
btngange.addActionListener(knappelytteren);
btnminus.addActionListener(knappelytteren);
btnpluss.addActionListener(knappelytteren);
btndel.addActionListener(knappelytteren);
}
class Knappelytter implements ActionListener{
public void actionPerformed (ActionEvent hendelse){
JButton valgtKnapp = (JButton) hendelse.getSource();
String knapp = valgtKnapp.getText();
if (knapp.equals("0")){
textfield += "0";
tekst.setText(textfield);
}else if(knapp.equals("1")){
textfield += "1";
tekst.setText(textfield);
}else if(knapp.equals("2")){
textfield += "2";
tekst.setText(textfield);
}else if(knapp.equals("3")){
textfield += "3";
tekst.setText(textfield);
}else if(knapp.equals("4")){
textfield += "4";
tekst.setText(textfield);
}else if(knapp.equals("5")){
textfield += "5";
tekst.setText(textfield);
}else if(knapp.equals("6")){
textfield += "6";
tekst.setText(textfield);
}else if(knapp.equals("7")){
textfield += "7";
tekst.setText(textfield);
}else if(knapp.equals("8")){
textfield += "8";
tekst.setText(textfield);
}else if(knapp.equals("9")){
textfield += "9";
tekst.setText(textfield);
}else if(knapp.equals("*")){
textfield += "*";
tekst.setText(textfield);
}else if(knapp.equals("/")){
textfield += "/";
tekst.setText(textfield);
}else if(knapp.equals("-")){
textfield += "-";
tekst.setText(textfield);
}else if(knapp.equals("+")){
textfield += "+";
tekst.setText(textfield);
}else if(knapp.equals("DEL")){
tekst.setText(" ");
textfield = " ";
}else if(knapp.equals("=")){
else if(knapp.equals("=")){
/EDIT RIGHT HERE
String[] parts = textfield.split("-*/+");
for (int i = 0; i < textfield.length(); i++){
if (textfield.charAt(i) == ('-')){
String one = parts[0];
String two = parts[1];
int one1 = Integer.parseInt(one);
int one2 = Integer.parseInt(two);
int one3 = one1-one2;
String one4 = String.valueOf(one3);
tekst.setText(one4);
}
}
}
}
public class MegetEnkelKalkis {
public static void main(String[] args) {
Kalkulator Skole = new Kalkulator("Kalkulator");
Skole.setVisible(true);
}
}
Get the Input
Seperate it from the Operands ( *, /, -, + )
Cast the strings to int's ( Integer.valueOf() throws a NumberFormatException)
Do a if else for the operands and then multiply, divide, add or substract the ints
What you need is a string calculator. You basically parse the contents of textfield following the regular maths rules. It is a bit of work but not too hard.
Basically just follow this:
Recursion might be quite suitable for that, so build a function that takes a string and returns the result as an int.
Search for all occurrences of a parameter (e.g. ) starting with the highest priority ones ( and /)
If you encounter that parameter split the string there into two halves (left of the parameter and right of the parameter)
Recursively follow the same rules with the left and right part of the string.
If the String only contains one number, parse that number using Integer.parseInt() and return it.
Calculate the result of left operator right, so e.g. left * right, if the operator is *
Return the result of the calculation.
Or you calculate via nashorn (javascript) engine ;)
private ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
double result = (double) scriptEngine.eval(formula)
You should build a reverse polish notation, which is the easiest way to parse and evaluate methmatical formulas. there are plenty of examples how to do that in Java on the web.
There are anumber of ways to do this, but recommendation is that you create two doubles. When the user clicks +,-,\ or * parse the number before it into a double. Thenwhen they press = parse everything between + and = into a double, then perform the calculation using those two doubles and output the result. You can set a flag to determine which operation to perform. for example the + button could set a boolean called Plus = true; Then when you perform the operation check which bools are true. IF more or less than one, tell the user the input was invalid, otherwise perform the operation
There is definitely lot of scope of improvement in the code, as suggested by others, but if you want to keep it as it is and working, then here is the code:
.
.
.
}else if(knapp.equals("=")){
String nytekst = textfield;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
Double result = (Double) engine.eval(nytekst);
System.out.println(result);
tekst.setText(result.toString());
} catch (ScriptException e) {
e.printStackTrace();
}
}
.
.
.
Related
I am working on a calculator with a GUI. I'm not sure how I should gather all the numbers from the user and do the math for them. I tried storing them in variables, but that doesn't really work since I need to be able to have multiple numbers and operators at one time. Any input would be greatly appreciated. Thanks!
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI extends JFrame implements ActionListener {
private JFrame frame;
private JPanel buttons;
//
private JPanel text;
private JTextField field;
//
private ImageIcon WCU;
private JLabel labelWCU;
///
JButton[] nums = new JButton[10];
JButton[] functions = new JButton[15];
ArrayList<Double> Addition = new ArrayList<>();
double A;
double S;
double M;
double D;
double Answer;
private JButton num1, num2, num3, num4, num5, num6, num7, num8, num9, num0;
private JButton decimal, add, subtract, multiply, divide, equals, squareRoot;
private JButton sin, cos, tan, exclamation, oneOverX, xSquared, log;
private JButton clear;
double input1 = 0, input2 = 0, answer = 0;
char op;
public GUI() {
frame = new JFrame();
buttons = new JPanel();
//
text = new JPanel();
field = new JTextField(30);
//
WCU = new ImageIcon("WCU.png");
labelWCU = new JLabel(WCU);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Calculator"); // make sure to center
frame.setSize(525,750);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setLayout(new BorderLayout());
frame.add(text, BorderLayout.NORTH);
frame.add(buttons, BorderLayout.CENTER);
text.add(field);
field.setEditable(false);
text.setBackground(Color.RED);
buttons.setBackground(Color.red);
buttons.setBorder(BorderFactory.createEmptyBorder(20,50,300,50));
buttons.setLayout(new GridLayout(6,4,20,20));
//
buttons.add(decimal = new JButton ("."));
functions[0] = decimal;
buttons.add(add = new JButton ("+"));
functions[1] = add;
buttons.add(subtract = new JButton ("-"));
functions[2] = subtract;
buttons.add(multiply = new JButton ("*"));
functions[3] = multiply;
buttons.add(divide = new JButton ("/"));
functions[4] = divide;
buttons.add(equals = new JButton ("="));
functions[5] = equals;
buttons.add(squareRoot = new JButton ("√"));
functions[6] = squareRoot;
buttons.add(num1 = new JButton ("1"));
nums[1] = num1;
buttons.add(num2 = new JButton ("2"));
nums[2] = num2;
buttons.add(num3 = new JButton ("3"));
nums[3] = num3;
buttons.add(num4 = new JButton ("4"));
nums[4] = num4;
buttons.add(num5 = new JButton ("5"));
nums[5] = num5;
buttons.add(num6 = new JButton ("6"));
nums[6] = num6;
buttons.add(num7 = new JButton ("7"));
nums[7] = num7;
buttons.add(num8 = new JButton ("8"));
nums[8] = num8;
buttons.add(num9 = new JButton ("9"));
nums[9] = num9;
buttons.add(num0 = new JButton ("0"));
nums[0] = num0;
buttons.add(sin = new JButton ("sin"));
functions[7] = sin;
buttons.add(cos = new JButton ("cos"));
functions[8] = cos;
buttons.add(tan = new JButton ("tan"));
functions[9] = tan;
buttons.add(exclamation = new JButton ("!"));
functions[10] = exclamation;
buttons.add(oneOverX = new JButton ("1/x"));
functions[11] = oneOverX;
buttons.add(xSquared = new JButton ("x^2"));
functions[12] = xSquared;
buttons.add(log = new JButton ("log"));
functions[13] = log;
text.add(clear = new JButton("Clear"));
functions[14] = clear;
labelWCU.setIcon(WCU);
frame.setVisible(true);
//
for (int i = 0; i < 15; i++){
functions[i].addActionListener(this);
functions[i].setFocusable(false);
}
for (int i = 0; i < 10; i++){
nums[i].addActionListener(this);
nums[i].setFocusable(false);
}
}
public void actionPerformed(ActionEvent e){
for (int i = 0; i < 10; i++){
if(e.getSource() == nums[i]){
field.setText(field.getText().concat(String.valueOf(i)));
}
}
if(e.getSource() == decimal){
field.setText(field.getText().concat("."));
}
if(e.getSource() == add){
A = Double.parseDouble(field.getText());
op = '+';
field.setText("");
}
if(e.getSource() == subtract){
input1 = Double.parseDouble(field.getText());
op = '-';
field.setText("");
}
if(e.getSource() == multiply){
input1 = Double.parseDouble(field.getText());
op = '*';
field.setText("");
}
if(e.getSource() == divide){
input1 = Double.parseDouble(field.getText());
op = '/';
field.setText("");
}
if(e.getSource() == equals){
field.setText(String.valueOf(Addition));
}
if(e.getSource() == clear){
field.setText("");
A = 0;
}
}
}
I don't fully understand the purpose of all fields in your class, so I'll propose my own set. If we (ab)use the text field as storage for the current value, two state fields are enough for the basic functionality. It's not necessary to store any more data:
private String firstBinaryOperand = null;
private char binaryOp = ' ';
These fields are used if there is a pending binary operation such as + or -. We don't need them for unary operations. For example, if the user types "700 + 200 =", then
When the "+" button is pressed for the first time, the currently displayed value (700) is stored in firstBinaryOperand and '+' in binaryOp.
When the "=" button is pressed, the current value (200) and the value cached in firstBinaryOperand are added and the result (900) written into the text field.
We therefore need a method that evaluates a pending binary operation if there is one and writes the result into the text field:
// Evaluate pending binary operation, if there is one.
private void evaluateBinaryOp() {
if (binaryOp != ' ') {
double firstOperand = Double.parseDouble(firstBinaryOperand);
double secondOperand = Double.parseDouble(field.getText());
double result;
if (binaryOp == '+') {
field.setText(Double.toString(firstOperand + secondOperand));
} else if (binaryOp == '-') {
field.setText(Double.toString(firstOperand - secondOperand));
}
// Implementation of further binary operands ...
// Update state, there is no longer a pending binary operation
firstBinaryOperand = null;
binaryOp = ' ';
}
}
Addition as an example of a binary operation:
if (e.getSource() == add){
evaluateBinaryOp(); // evaluate pending binary op, if any
firstBinaryOperand = field.getText();
binaryOp = '+';
field.setText("0");
}
Unary operations are simpler, but we still have to check whether there is a pending binary operation and evaluate it first if this is the case:
if (e.getSource() == oneOverX) {
evaluateBinaryOp(); // evaluate pending binary op, if any
double currentValue = Double.parseDouble(field.getText());
field.setText(Double.toString(1.0 / currentValue));
}
All other unary and binary operations can be implemented using the same pattern.
This is going to give you a very basic calculator whose behavior differs a bit from the usual. For example, if the user presses +, they will not see the intermediate result but always 0. The intermediate result isn't lost though as it is stored in the firrstBinaryOperand field in the background. The correct result will be shown once = or another unary operator is used. I hope this answers your question and is enough to get you started, you can then refine the behavior in a second step.
I made a GUI which basically adds the numbers from the two textfield. The problem is, if I leave the other textfield blank and the other textfield has a number, the result textfield is not updating.
public class AdditionGui extends JFrame implements ActionListener {
private TextField tf1 , tf2 , tf3;
private Label sign, equalsign;
private int sum = 0;
AdditionGui(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
tf1 = new TextField(5);
add(tf1);
tf1.addActionListener(this);
sign = new Label("+");
add(sign);
tf2 = new TextField(5);
add(tf2);
tf2.addActionListener(this);
equalsign = new Label("=");
add(equalsign);
tf3 = new TextField(5);
add(tf3);
setTitle("Sum of two numbers");
setSize(220,120);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
int val1 = Integer.parseInt(tf1.getText());
int val2 = Integer.parseInt(tf2.getText());
sum = val1 + val2;
tf3.setText("" + sum);
}
}
A blank text field means its contents cannot be parsed to an Integer. In that case this line of your code will throw NumberFormatException (if tf1 is blank).
int val1 = Integer.parseInt(tf1.getText());
In your actionPerformed() method, check that getText() returns a number.
I suggest setting a blank text field to zero, for example:
String text1 = tf1.getText();
if (text1.length() == 0) {
text1 = "0";
}
int val1 = Integer.parseInt(text1);
String text2 = tf2.getText();
if (text2.length() == 0) {
text2 = "0";
}
int val2 = Integer.parseInt(text2);
int sum = val1 + val2;
tf3.setText(Integer.toString(sum));
Now something for you to think about.
What happens if the user enters a non-digit into one of the text fields?
I have been creating a calculator as a beginner in Java. I have added in buttons that have a more complex functionality, and for some reason they just don't work.
Can somebody please educate me on why these java calculations are not working properly?
The buttons that work fine are the plus, minus, multiply and divide.
The buttons that aren't working so well are the percentage, squareRt, and the PlusMinus buttons.
You can see in the calculator engine that I have implemented the correct method of calculation, however when the problematic buttons are pressed, the text display area of the calculator goes blank, when for example, if you press in 64 on the calculator and then press sqrt, it is suppose to display the Square root of 64, but is not doing so. Thanks for any help in advance. (take it easy on me i'm a beginner)
Here is the calculator
package Calculator;
import javax.swing.*;
import java.awt.GridLayout;
import java.awt.BorderLayout;
public class Calculator {
// Declare and instantiate window components
JButton button0 = new JButton("0");
JButton button1 = new JButton("1");
JButton button2 = new JButton("2");
JButton button3 = new JButton("3");
JButton button4 = new JButton("4");
JButton button5 = new JButton("5");
JButton button6 = new JButton("6");
JButton button7 = new JButton("7");
JButton button8 = new JButton("8");
JButton button9 = new JButton("9");
JButton buttonPoint = new JButton(".");
JButton buttonEqual = new JButton("=");
JButton buttonPlus = new JButton("+");
JButton buttonMinus = new JButton("-");
JButton buttonDivide = new JButton("/");
JButton buttonMultiply = new JButton("*");
JButton buttonSquareRt = new JButton("sqrt");
JButton buttonPercentage = new JButton("%");
JButton buttonPlusMinus = new JButton("+/-");
JButton buttonClear = new JButton("C");
JPanel windowContent = new JPanel();
JTextField displayField = new JTextField(30);
// Constructor
Calculator() {
// Set the layout manager for this panel
BorderLayout bl = new BorderLayout();
windowContent.setLayout(bl);
// Add the display field to the top of the window
windowContent.add("North", displayField);
// Create the panel with the GridLayout
// that will contain 12 buttons - 10 numeric ones, and
// buttons with the point and the equal sign
JPanel p1 = new JPanel();
GridLayout gl = new GridLayout(4, 3);
p1.setLayout(gl);
p1.add(button1);
p1.add(button2);
p1.add(button3);
p1.add(button4);
p1.add(button5);
p1.add(button6);
p1.add(button7);
p1.add(button8);
p1.add(button9);
p1.add(button0);
p1.add(buttonPoint);
p1.add(buttonEqual);
// Add the panel p1 to the centre area of the window
windowContent.add("Center", p1);
// Create the panel with the GridLayout
// that will contain 4 action buttons -
// Plus, Minus, Divide and Multiply
JPanel p2 = new JPanel();
GridLayout gl2 = new GridLayout(4, 1);
p2.setLayout(gl);
p2.add(buttonPlus);
p2.add(buttonMinus);
p2.add(buttonMultiply);
p2.add(buttonDivide);
//adding the task buttons to go on extra column
p2.add(buttonSquareRt);
p2.add(buttonPercentage);
p2.add(buttonPlusMinus);
p2.add(buttonClear);
// Add the panel p2 to the east area of the window
windowContent.add("East", p2);
// Create the frame and add the content pane to it
JFrame frame = new JFrame("Calculator");
frame.setContentPane(windowContent);
// set the size of the window to be big enough to
// accommodate all window controls
frame.pack();
// Display the window
frame.setVisible(true);
// Instantiate the event listener and
// register each button with it
CalculatorEngine calcEngine = new CalculatorEngine(this);
button0.addActionListener(calcEngine);
button1.addActionListener(calcEngine);
button2.addActionListener(calcEngine);
button3.addActionListener(calcEngine);
button4.addActionListener(calcEngine);
button5.addActionListener(calcEngine);
button6.addActionListener(calcEngine);
button7.addActionListener(calcEngine);
button8.addActionListener(calcEngine);
button9.addActionListener(calcEngine);
buttonPoint.addActionListener(calcEngine);
buttonPlus.addActionListener(calcEngine);
buttonMinus.addActionListener(calcEngine);
buttonDivide.addActionListener(calcEngine);
buttonMultiply.addActionListener(calcEngine);
buttonEqual.addActionListener(calcEngine);
buttonSquareRt.addActionListener(calcEngine);
buttonPercentage.addActionListener(calcEngine);
buttonPlusMinus.addActionListener(calcEngine);
buttonClear.addActionListener(calcEngine);
}
public static void main(String[] args) {
// Instantiate the class Calculator
Calculator calc = new Calculator();
}
}
And here is the engine with the problematic code
package Calculator;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
public class CalculatorEngine implements ActionListener {
Calculator parent; // a reference to Calculator window
char selectedAction = ' '; // +, -, /, or *
double currentResult = 0;
// Constructor stores the reference to the Calculator
// window in the member variable parent
CalculatorEngine(Calculator parent) {
this.parent = parent;
}
public void actionPerformed(ActionEvent e) {
// Get the source of this action
JButton clickedButton = (JButton) e.getSource();
String dispFieldText = parent.displayField.getText();
double displayValue = 0;
// Get the number from the text field
// if it’s not empty
if (!"".equals(dispFieldText)) {
displayValue = Double.parseDouble(dispFieldText);
}
Object src = e.getSource();
// For each action button memorize selected
// action +, -, /, or *, store the current value
// in the currentResult, and clean up the display
// field for entering the next number
if (src == parent.buttonPlus) {
selectedAction = '+';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonMinus) {
selectedAction = '-';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonDivide) {
selectedAction = '/';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonMultiply) {
selectedAction = '*';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonSquareRt) {
selectedAction = 's';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonPercentage){
selectedAction = 'p';
currentResult = displayValue;
parent.displayField.setText("");
} else if (src == parent.buttonPlusMinus){
selectedAction = 'm';
currentResult = displayValue;
parent.displayField.setText("");
}
else if (src == parent.buttonEqual) {
// Perform the calculations based on selectedAction
// update the value of the variable currentResult
// and display the result
if (selectedAction == '+') {
currentResult += displayValue;
// Convert the result to String by concatenating
// to an empty string and display it
parent.displayField.setText("" + currentResult);
} else if (selectedAction == '-') {
currentResult -= displayValue;
parent.displayField.setText("" + currentResult);
} else if (selectedAction == '/') {
currentResult /= displayValue;
parent.displayField.setText("" + currentResult);
} else if (selectedAction == '*') {
currentResult *= displayValue;
parent.displayField.setText("" + currentResult);
} else if (selectedAction == 's') {
currentResult = Math.sqrt(displayValue);
parent.displayField.setText("" + currentResult);
} else if (selectedAction == 'p') {
currentResult = currentResult / 100;
parent.displayField.setText("" + currentResult);
} else if (selectedAction == 'm') {
displayValue = currentResult * -1;
parent.displayField.setText("" + currentResult);
}
} else {
// For all numeric buttons append the button's
// label to the text field
String clickedButtonLabel = clickedButton.getText();
parent.displayField.setText(dispFieldText + clickedButtonLabel);
}
}
}
It appears that this code would work as expected where you would type a number like 64, then you would press the square root button - which would clear the displayField - then you would press the equals button, and it would display the result.
If you want to make it more obvious that you should be pressing the equals button to get the result, you might want to echo the users entry surrounded by text that represents the function to be performed, for example:
else if (src == parent.buttonSquareRt) {
selectedAction = 's';
currentResult = displayValue;
parent.displayField.setText("sqrt(" + currentResult + ")");
}
I have created a GUI calculator program, that performs calculations in a linear order, but i want it to perform calculations in an order of "Divide, multiply, add, subtract".
I'm a beginner, so please suggest me if there is any other simpler way to implement the same thing, which I have coded.
Please help me with the 'DMAS' thing.
My code:
public class keypadGUI extends JFrame{
private JTextField lcd;
private JButton n1,n2,n3,n4,n5,n6,n7,n8,n9,n0;
private JButton plus,minus,multiply,divide,equalTo,dot;
//private JButton[] buttons = new JButton[10];
//private JButton[] opButtons = new JButton[6];
private double ans = 0; //For storing final ans
char[] op; //Character array for stroing operators
private double[] nums; //For storing the numbers
public JPanel keypad;
private StringBuilder sb = new StringBuilder(); //For storing the input of the user as string
public keypadGUI(){
setLayout(new BorderLayout(10,10));
lcd = new JTextField();
lcd.setEditable(false);
Border low = BorderFactory.createLoweredSoftBevelBorder();
lcd.setBorder(low);
lcd.setHorizontalAlignment(JTextField.RIGHT);
lcd.setFont(new Font("Serif",Font.BOLD,30));
lcd.setText("0");
Font numFont = new Font("Serif",Font.BOLD,20);
n1 = new JButton("1"); n2 = new JButton("2"); n3 = new JButton("3"); n4 = new JButton("4");
n5 = new JButton("5"); n6 = new JButton("6"); n7 = new JButton("7"); n8 = new JButton("8");
n9 = new JButton("9"); n0 = new JButton("0"); dot = new JButton(".");
plus = new JButton("+");
minus = new JButton("-");
multiply = new JButton("*");
divide = new JButton("/");
equalTo = new JButton("=");
n1.setFont(numFont); n2.setFont(numFont); n3.setFont(numFont); n4.setFont(numFont);
n5.setFont(numFont); n6.setFont(numFont); n7.setFont(numFont); n8.setFont(numFont);
n9.setFont(numFont); n0.setFont(numFont); dot.setFont(numFont); plus.setFont(numFont);
minus.setFont(numFont); multiply.setFont(numFont); divide.setFont(numFont); equalTo.setFont(numFont);
plus.setForeground(Color.DARK_GRAY); minus.setForeground(Color.DARK_GRAY); multiply.setForeground(Color.DARK_GRAY);
divide.setForeground(Color.DARK_GRAY); equalTo.setForeground(Color.DARK_GRAY);
listen listener = new listen();
n1.addActionListener(listener); n2.addActionListener(listener); n3.addActionListener(listener); n4.addActionListener(listener);
n5.addActionListener(listener); n6.addActionListener(listener); n7.addActionListener(listener); n8.addActionListener(listener);
n9.addActionListener(listener); n0.addActionListener(listener); plus.addActionListener(listener); minus.addActionListener(listener);
multiply.addActionListener(listener); divide.addActionListener(listener);
equalTo.addActionListener(new equalListener());
keypad = new JPanel(new GridLayout(4,4,10,10));
keypad.add(n7); keypad.add(n8); keypad.add(n9); keypad.add(divide);
keypad.add(n4); keypad.add(n5); keypad.add(n6); keypad.add(multiply);
keypad.add(n1); keypad.add(n2); keypad.add(n3); keypad.add(plus);
keypad.add(n0); keypad.add(dot); keypad.add(equalTo); keypad.add(minus);
add(lcd,BorderLayout.NORTH);
add(keypad,BorderLayout.CENTER);
setVisible(true);
setLookAndFeel();
setSize(280,280);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("MY Calc");
}
private void setLookAndFeel(){
try{
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}catch(Exception ae){}
}
private class listen implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
String bName = ((JButton)e.getSource()).getText();
sb.append(bName);
lcd.setText(sb.toString());
}
}
private class equalListener implements ActionListener{
public void actionPerformed(ActionEvent e){
String[] tokkens = sb.toString().split("-|\\+|\\*|\\/");
nums = new double[tokkens.length];
for(int i=0;i<nums.length;i++){
nums[i] = Double.parseDouble(tokkens[i]);
}
op = new char[10];
op[0]='+';
int c =1;
for(int i=0;i<sb.length();i++){
if(sb.charAt(i)=='+' || sb.charAt(i)=='-' || sb.charAt(i)=='*' || sb.charAt(i)=='/')
{ op[c]=sb.charAt(i); c++; }
}
performOP();
sb = sb.delete(0, sb.length());
sb.append(ans);
lcd.setText(sb.toString());
System.out.println(op);
System.out.println(Arrays.toString(tokkens));
}
}
private void performOP(){
for(int i=0;i<nums.length;i++){
switch(op[i]){
case '+':
ans = ans + nums[i];
break;
case '-':
ans = ans - nums[i];
break;
case '*':
ans = ans * nums[i];
break;
case '/':
ans = ans / nums[i];
break;
default:
System.out.println("INVALID CASE !!!");
}
}
}
}
You currently have a linear approach to understanding the expression, you build a list of operators and execute them in order.
You need to build something more like a tree so that you can give your desired meaning to
3 + 4 * 5
and you probably want to allow parentheses too
2 + ( 3 * 4) + ( 5 * ( 6 + 7 ) )
This is a very common parsing problem, generally known as recursive descent parsing. You will be able to find libraries that implement such parsers. For example ANTLR. It's quite a big jump from where you are to this sort of stuff. If you dig around you'll probably find simple implementations you can clone, but if you really want to understand the area then you'd need to study quite a bit: articles such as this may help.
Umm , how about if you just store all the characters that you take as operands and operators in a linked list. Store all the operators in an array, according to their precedence. Such as, arr[]={'/','*','+','-'}, iterate through these operators. While you are doing that detect any of the operation that needs to be applied first , store its answer in a new node, then delete those nodes containing the detected operations and operands.Link the new node to the node after the last operand upon which operation was being performed upon. You can repeat this process, until the base or head node's next pointer becomes zero.And yeah honestly, iam also kind of a beginner to this matter,so this solution is obviously not great. I also kind of thought this just right now and ofcourse havenot implemented this idea myself. But yeah , you can give it a shot, if you want to though.Hope it helps, even if just a bit.
I am writing a Mortgage Calculator for class and I have it working the way I need it to, except everytime I click the "Calculate" button it will just continue to add to the table instead of the table clearing and showing new values. I know my code might look a little sloppy and I have some things commented out that don't need to be there because I'm still working it, but do you have any suggestions?
FYI I am still a beginner learning Java and it has taken me over 20hrs to get this far (and i"m pretty proud of myself!) Thank you!!
//Import all required Packages
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
public class MortgageCalculator extends JFrame implements ActionListener {
// Loan Values
double intPrincipal, interestRate, calcPayment, monthlyInterest, currentInterest, principalPaid, newBalance;
int totalMonths;
double[] loanInterest = {5.35, 5.5, 5.75}; // Yearly interest in decimal form
int[] loanTerm = {7, 15, 30}; // Total months of term
String principal;
String comboArray[] = {"7 Years at 5.35%", "15 Years at 5.5%", "30 Years at 5.75%"};
int termYears, termMonths, done, i=0, m=0, p=0;
//Set up panels
JPanel contentPanel;
//Set up labels
JLabel mortgageLabel, paymentLabel, termLabel;
//Set up buttons
JButton calculateButton, clearButton, exitButton;
//TextFields
JTextField txtMortgage = new JTextField(10);
JTextField txtPayment = new JTextField(10);
//New Text Area
JTextArea textarea = new JTextArea();
DecimalFormat df = new DecimalFormat("$###,###.00"); //Formatting the results to decimal form
//Combo Box
JComboBox loansList = new JComboBox();
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
//Build GUI
public MortgageCalculator()
{
super();
initializeContent();
}
public void initializeContent()
{
this.setSize(700, 500);
this.setLocation(0, 0);
this.setContentPane(contentPanel());
this.setTitle("Mortgage Calculator");
}
public JPanel contentPanel()
{
contentPanel = new JPanel();
contentPanel.setLayout(null);
//Add labels to the panel
mortgageLabel = new JLabel("Mortgage:");
mortgageLabel.setLocation(200, 30);
mortgageLabel.setSize(100, 25);
contentPanel.add(mortgageLabel);
termLabel = new JLabel("Term & Rate:");
termLabel.setLocation(183, 55);
termLabel.setSize(100, 30);
contentPanel.add(termLabel);
paymentLabel = new JLabel("Monthly Payment:");
paymentLabel.setLocation(158, 85);
paymentLabel.setSize(100, 30);
contentPanel.add(paymentLabel);
//Text Fields
txtMortgage = new JTextField(10);
txtMortgage.setLocation(280, 30);
txtMortgage.setSize(150, 25);
contentPanel.add(txtMortgage);
txtPayment = new JTextField(10);
txtPayment.setLocation(280, 85);
txtPayment.setSize(150, 25);
contentPanel.add(txtPayment);
//Combo Box
loansList.addItem(comboArray[0]);
loansList.addItem(comboArray[1]);
loansList.addItem(comboArray[2]);
loansList.setLocation(280, 55);
loansList.setSize(150, 25);
loansList.addActionListener(this);
contentPanel.add(loansList);
//textarea.setPreferredSize(new Dimension(650, 300));
//JScrollPane scroller = new JScrollPane(textarea);
JScrollPane scroller = new JScrollPane(table);
contentPanel.add(scroller);
scroller.setSize(650,300);
scroller.setLocation(20, 150);
textarea.setLineWrap(true);
model.addColumn("Payment Number");
model.addColumn("Current Interest");
model.addColumn("Principal Paid");
model.addColumn("New Balance");
//Buttons
exitButton = new JButton("Exit");
exitButton.setLocation(450, 30);
exitButton.setSize(100, 25);
contentPanel.add(exitButton);
clearButton = new JButton("Clear");
clearButton.setLocation(450, 55);
clearButton.setSize(100, 25);
contentPanel.add(clearButton);
calculateButton = new JButton("Calculate");
calculateButton.setLocation(450, 85);
calculateButton.setSize(100, 25);
contentPanel.add(calculateButton);
//setup up buttons
calculateButton.addActionListener(this);
clearButton.addActionListener(this);
exitButton.addActionListener(this);
return contentPanel;
}
//Define actions performed for buttons
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
if (e.getSource() == loansList) {
switch (loansList.getSelectedIndex()) {
case 0:
i = 0;
break;
case 1:
i = 1;
break;
case 2:
i = 2;
break;
}
}
if (arg == "Calculate")
{
txtPayment.setText("");
principal = txtMortgage.getText();
try {
intPrincipal = Double.parseDouble(principal);
if (intPrincipal <= 0) throw new NumberFormatException();
}
catch(NumberFormatException n){
txtPayment.setText("Please Enter a Postive Numeric Number");
done = 1;
}
if (done == 1)
done = 0;
else {
interestRate = loanInterest[i];
termYears = loanTerm[i];
monthlyInterest = interestRate/(12*100); //calculates monthly interest
termMonths = termYears*12; //calculates term length in months
calcPayment = monthlyInterest*intPrincipal/(1-Math.pow((1+monthlyInterest), -termMonths)); //calculates monthly payment
txtPayment.setText(" " + df.format(calcPayment));
for (m=0; m<=totalMonths; m++) {
totalMonths = loanTerm[i]*12;
currentInterest = intPrincipal * monthlyInterest;
principalPaid = calcPayment - currentInterest;
newBalance = intPrincipal - principalPaid;
intPrincipal = newBalance;
/* printAndAppend(
(m+1) + " " +
df.format(currentInterest) + " " +
df.format(principalPaid) + " " +
df.format(newBalance) + "\n");
//textarea.setText(df.format(currentInterest));
if(intPrincipal <= 1){ break;}*/
// Create a couple of columns
model.addRow(new Object[]{m+1, df.format(currentInterest), df.format(principalPaid), df.format(newBalance)});
if(intPrincipal <= 1){ break;}
}
}
}
else if (e.getSource() == clearButton)
{
txtMortgage.setText(""); //clear Mortgage textfield
txtPayment.setText(""); //clear Payment textfield
txtMortgage.requestFocusInWindow(); //move cursor back to Mortgage textfield
loansList.setSelectedIndex(0);
}
else if (e.getSource() == exitButton)
System.exit(0);
}
public void printAndAppend(String text) {
textarea.append(text);
}
public static void main(String[] args)
{
new MortgageCalculator().setVisible(true);
}
}
To clear all you need to do is set the row count of the model to 0 -- that's it:
else if (e.getSource() == clearButton) {
txtMortgage.setText("");
txtPayment.setText("");
txtMortgage.requestFocusInWindow();
loansList.setSelectedIndex(0);
model.setRowCount(0); //!! added
}
Also, this is not good:
if (arg == "Calculate") {
As you shouldn't use == to compare Strings. If you want to compare Strings, use the equals method:
if (arg.equals("Calculate")) {
or the equalsIgnoreCase method:
if (arg.equalsIgnoreCase("Calculate")) {
The reason this is important is because == checks to see if one String object is the same as another String object, and you really don't care about this. Instead you want to know if one String holds the same chars as another, and that's what equals tests for.
Also, I'd set the model's row count to 0 at the beginning of your calculate method, and this way you can recalculate things without having to clear.