KeyBinding,无法获取按下的键的String

时间:2013-12-15 12:18:42

标签: java nullpointerexception action jbutton key-bindings

好的,这是代码

     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);
    }
}

我收到此错误“线程中的异常”AWT-EventQueue-0“java.lang.NullPointerException     在mainProgram.Gui $ 1.actionPerformed(Gui.java:225)“。我最好的猜测是我的String op没有值,所以当我点击键盘上的”=“按钮时,编译器不知道切换到哪种情况但是我不明白为什么op没有从我的“/”,“*”,“ - ”,“+”案例中获取ActionCommand的值。

例如,如果我在程序中写了一个数字,那么我点击键盘上的“/”按钮,程序似乎做了AbstractAction方法中“/”情况下的任何内容,但后来我写了第二个数字,单击键盘上的“=”按钮我收到此错误。有什么快速解决方法吗?

1 个答案:

答案 0 :(得分:1)

该行中的

op必须为null

op之外定义actionPerformed变量。

因此它将始终包含最后执行的操作。

如果您启动调试器并进入actionPerformed,您会注意到原因。

当调用方法时,会创建变量op,然后为其赋值。然后方法结束,变量也结束。

下次创建方法时,会创建一个值为null的新变量。然后你到达

            case "=":
                switch (op) {

其中op必须为null,因为自创建以来尚未为其分配值。

如果您将op放在actionPerformed之外,它会在方法完成后保留其值。它应该被称为lastOp,以反映它是在方法的最后一次运行时分配的。

(请注意,在多线程环境中,这种方法可能会有危险,但对于GUI来说,它应该足够好了。)

建议您如何改进actionPerformed方法。记住这个概念:不要重复自己。

        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;
        }