Question

Ok so here is the code

     Gui.java
      package mainProgram;

    import javax.swing.*;

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;

    public class Gui extends JFrame {
        final private static JButton numberButtons[] = new JButton[10];
        private JButton sum = new JButton("+");
        private JButton substract = new JButton("-");
        private JButton divide = new JButton("/");
        private JButton multiply = new JButton("*");
        private JButton sqrt = new JButton("√");
        private JButton square = new JButton("x^2");
        private JButton cubic = new JButton("x^3");
        private JButton percentage = new JButton("%");
        private JButton divideByOne = new JButton("1/x");
        private JButton C = new JButton("C");
        private JButton OK = new JButton("=");
        private JButton point = new JButton(".");
        private JButton plusMinus = new JButton("+-");
        private JTextArea output = new JTextArea();
        private JTextField inputOne = new JTextField();
        private JPanel panel = new JPanel();
        functions fn = new functions();
        GuiUpdate gridBagConstr = new GuiUpdate();
        HandlerClass handler = new HandlerClass();


        public Gui() {

            super("Calculator");
            setLayout(new GridBagLayout());
            requestFocus();

            output.setEditable(false);
            output.setBackground(Color.GREEN);
            // keyBinding for 0-9
            for (int i = 0; i <= numberButtons.length - 1; i++) {
                String text = String.valueOf(i);
                JButton button = new JButton(text);
                button.addActionListener(numberAction);
                numberButtons[i] = button;
                add(button);

                // Support Key Bindings

                KeyStroke pressed = KeyStroke.getKeyStroke(text);
                InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
                inputMap.put(pressed, text);
                button.getActionMap().put(text, numberAction);
            }// keyBinding for NUMPAD 0-9
            for (int i = 0; i <= numberButtons.length - 1; i++) {
                String text = String.valueOf(i);
                KeyStroke pressed = KeyStroke.getKeyStroke(0x60 + i, 0);
                InputMap inputMap = numberButtons[i]
                        .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
                inputMap.put(pressed, text);
                numberButtons[i].getActionMap().put(text, numberAction);

            }


            // add Key Bindings listeners
            substract.addActionListener(numberAction);
            sum.addActionListener(numberAction);
            divide.addActionListener(numberAction);
            multiply.addActionListener(numberAction);
            //keyBinding for divide button
            KeyStroke pressed1 = KeyStroke.getKeyStroke(KeyEvent.VK_DIVIDE, 0);
            divide.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(pressed1,"divide");
            divide.getActionMap().put("divide", numberAction);
            //keyBinding for sum button
            KeyStroke pressed2 = KeyStroke.getKeyStroke( 0x6B, 0);
            sum.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(pressed2, "add");
            sum.getActionMap().put("add", numberAction);
            //keyBinding for equal button
            KeyStroke pressed3 = KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, 0);
            OK.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(pressed3, "=");
            OK.getActionMap().put("=", numberAction);



            gridBagConstr.setConstrains("HORIZONTAL", 4, 1, 0, 0, 30);
            add(output, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 4, 1, 0, 1, 15);
            add(inputOne, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 0, 2, 0);
            add(divide, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 1, 2, 0);
            add(multiply, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 2, 2, 0);
            add(substract, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 3, 2, 0);
            add(sum, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 4, 2, 0);
            add(divideByOne, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 0, 3, 0);
            add(numberButtons[7], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 1, 3, 0);
            add(numberButtons[8], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 2, 3, 0);
            add(numberButtons[9], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 3, 3, 0);
            add(sqrt, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 0, 4, 0);
            add(numberButtons[4], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 1, 4, 0);
            add(numberButtons[5], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 2, 4, 0);
            add(numberButtons[6], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 3, 4, 0);
            add(square, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 0, 5, 0);
            add(numberButtons[1], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 1, 5, 0);
            add(numberButtons[2], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 2, 5, 0);
            add(numberButtons[3], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 3, 5, 0);
            add(cubic, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 0, 8, 0);
            add(numberButtons[0], gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 1, 8, 0);
            add(point, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 2, 8, 0);
            add(C, gridBagConstr.c);
            gridBagConstr.setConstrains("HORIZONTAL", 1, 1, 3, 8, 0);
            add(OK, gridBagConstr.c);
            // actionListeners for other operations and for input from the program not from keyboard
            inputOne.addActionListener(handler);
            divide.addActionListener(handler);
            multiply.addActionListener(handler);
            substract.addActionListener(handler);
            sum.addActionListener(handler);
            divideByOne.addActionListener(handler);
            sqrt.addActionListener(handler);
            square.addActionListener(handler);
            cubic.addActionListener(handler);
            point.addActionListener(handler);
            C.addActionListener(handler);
            OK.addActionListener(handler);


        }

        public void eraseData() {
            fn.setA(0);
            inputOne.setText("");

        }

        public void saveInput() {
            if (fn.isNumeric(inputOne.getText())) {
                fn.setResult(Double.parseDouble(inputOne.getText()));
                output.setText(inputOne.getText());
            }
        }

        Action numberAction = new AbstractAction() {

            public void actionPerformed(ActionEvent e) {

                String x = e.getActionCommand();
                String op = null ; 
                switch (x) {
                case "0":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "1":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "2":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "3":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "4":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "5":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "6":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "7":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "8":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "9":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case ".":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "/":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "*":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "-":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "+":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "=":
                    switch (op) {
                    case "/":
                        fn.divide(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "*":
                        fn.multiply(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "+":
                        fn.sum(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "-":
                        fn.substract(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                }
            }
        };

        private class HandlerClass implements ActionListener {
            String op;

            public void actionPerformed(ActionEvent e) {

                String x = e.getActionCommand();
                switch (x) {
                case ".":
                    inputOne.setText(inputOne.getText() + x);
                    break;
                case "/":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "*":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "-":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "+":
                    op = e.getActionCommand();
                    saveInput();
                    eraseData();
                    break;
                case "√":
                    if (outputCheckZero(inputOne.getText())) {
                        fn.sqrt(output.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    } else {
                        fn.sqrt(inputOne.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                case "x^2":
                    if (outputCheckZero(inputOne.getText())) {
                        fn.square(output.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    } else {
                        fn.square(inputOne.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                case "x^3":
                    if (outputCheckZero(inputOne.getText())) {
                        fn.cubic(output.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    } else {
                        fn.cubic(inputOne.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                case "%":
                    break;
                case "1/x":
                    if (outputCheckZero(inputOne.getText())) {
                        fn.divideByOne(output.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    } else {
                        fn.divideByOne(inputOne.getText());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                case "C":
                    eraseData();
                    output.setText("");
                    fn.setResult(0);
                    break;
                case "=":
                    switch (op) {
                    case "/":
                        fn.divide(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "*":
                        fn.multiply(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "+":
                        fn.sum(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    case "-":
                        fn.substract(inputOne.getText(), fn.getResult());
                        output.setText(Double.toString(fn.getResult()));
                        eraseData();
                    }
                    break;
                case "+-":
                    break;
                default:
                    break;
                }

            }

            public boolean outputCheckZero(String x) {
                if (x.isEmpty())
                    return true;
                else
                    return false;
            }
        }
    }

     functions.java
    package mainProgram;

    import java.math.*;
    import java.util.*;

    public class functions {

        private double a;
        private double result = 0;

        public boolean isNumeric(String x) {
            try {
                Double.parseDouble(x);
                return true;
            } catch (NumberFormatException nfe) {
            }
            return false;

        }

        public double getNumber(String x) {
            if (isNumeric(x)) {
                this.a = Double.parseDouble(x);
            }
            return a;
        }

        public double sum(String a, double b) {
            if (isNumeric(a)) {
                double c = getNumber(a);
                result = b + c;
                return result;
            } else
                return b;

        }

        public double divide(String a, double b) {
            if (isNumeric(a)) {
                double c = getNumber(a);

                result = b / c;
                return result;
            } else
                return b;

        }

        public double multiply(String a, double b) {
            if (isNumeric(a)) {
                double c = getNumber(a);

                result = b * c;
                return result;
            } else
                return b;
        }

        public double substract(String a, double b) {
            if (isNumeric(a)) {
                double c = getNumber(a);

                result = b - c;
                return result;
            } else
                return b;
        }

        public double sqrt(String a) {
            if (isNumeric(a)) {
                double c = getNumber(a);
                result = Math.sqrt(c);
                return result;
            } else
                return 0;
        }

        public double square(String a) {
            if (isNumeric(a)) {
                double c = getNumber(a);
                result = c * c;
                return result;
            } else
                return 0;
        }

        public double cubic(String a) {
            if (isNumeric(a)) {
                double c = getNumber(a);
                result = c * c * c;
                return result;
            } else
                return 0;
        }

        public double divideByOne(String a) {
            if (isNumeric(a)) {
                double c = getNumber(a);
                result = 1 / c;
                return result;
            } else
                return 0;
        }

        public double getA() {
            return a;
        }

        public void setA(double a) {
            this.a = a;
        }

        public double getResult() {
            return result;
        }

        public void setResult(double result) {
            this.result = result;
        }
    }

package mainProgram;

import java.awt.GridBagConstraints;

public class GuiUpdate extends GridBagConstraints {

    GridBagConstraints c = new GridBagConstraints();

    public void setConstrains (String FILL, int gridwidth, int gridheight, int gridx, int gridy, int ipady ){
        if(FILL.toUpperCase().equals("HORIZONTAL")){
            this.c.fill = GridBagConstraints.HORIZONTAL;
            }else if(FILL.toUpperCase().equals("VERTICAL")){
                c.fill = GridBagConstraints.VERTICAL;
            }else if (FILL.toUpperCase().equals("BOTH")){
                c.fill = GridBagConstraints.BOTH;
            }else c.fill = GridBagConstraints.NONE;
            this.c.gridwidth = gridwidth;
            this.c.gridheight = gridheight;
            this.c.gridx = gridx;
            this.c.gridy = gridy;
            this.c.ipady = ipady;

    }

}

package mainProgram;
import javax.swing.JFrame;
public class mainClass {

    public static void main(String[] args) {

        Gui go = new Gui();
        go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        go.setSize(250,400);
        go.setVisible(true);
    }
}

I get this error " Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at mainProgram.Gui$1.actionPerformed(Gui.java:225)". My best guess is that my String op has no value, so when I click the "=" button on my keyboard the compiler has no idea which case to switch to. But what I don't understand is why the op doesn't take the value of the ActionCommand from my "/","*","-","+" cases.

For example if I write a number in my program then I click the "/" button on my keyboard the program seems to do whatever is in the "/" case from the AbstractAction method, but then I write the second number and click the "=" button on the keyboard I get this error. Any quick fix for it?

Was it helpful?

Solution

op must be null in that line.

Define a op variable outside of actionPerformed.

Thus it will always contain the last operation performed.

If you start a debugger and step into actionPerformed you will notice why.

When the method is called the variable op is created, then you assign a value to it. Then the method ends and so does the variable.

The next time the method is created, a new variable is created with the value null. You then reach the lines

            case "=":
                switch (op) {

where op must be null, because it has not been assigned a value since it was created.

If you place op outside of actionPerformed it keeps its value after the method finished. It should be called lastOp to reflect that it was assigned at the last run of the method.

(Please be aware that in multi-threadding environments this approach may be hazardous, for GUIs it should be good enough, though.)

As a suggestion on how you could improve your actionPerformed method. Remember the concept: Don't repeat yourself.

        String lastOp = null ; 
        public void actionPerformed(ActionEvent e) {

            String x = e.getActionCommand();
            switch (x) {
            case "/": // an empty case line will execute the elements of the next case.
            case "*": // repeatative, so all operator cases here will execute the
            case "-": // "+" case, but with their operator.
            case "+":
                lastOp = e.getActionCommand();
                saveInput();
                eraseData();
                break;
            case "=":
                switch (op) {
                case "/":
                    fn.divide(inputOne.getText(), fn.getResult());
                case "*":
                    fn.multiply(inputOne.getText(), fn.getResult());
                case "+":
                    fn.sum(inputOne.getText(), fn.getResult());
                case "-":
                    fn.substract(inputOne.getText(), fn.getResult());
                }
                output.setText(Double.toString(fn.getResult()));
                eraseData();
                lastOp = null;
                break;
            }
            default: // this handles all number cases.
                inputOne.setText(inputOne.getText() + x);
                break;
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top