Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Here's my complete code for reference, in case the error has nothing to do with the block in question:

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

//Previously while debugging this, I was writing my own exception in case of an arithmetic
//error.  I'm trying to get it to work so my evaluation method has a catch block, which is
//necessary because the ScriptEngineManager requires it.
public class Calculator
{
    JButton button0;
    JButton button1;
    JButton button2;
    JButton button3;
    JButton button4;
    JButton button5;
    JButton button6;
    JButton button7;
    JButton button8;
    JButton button9;
    JButton buttonCE;
    JButton buttonC;

    JButton buttonPlus;
    JButton buttonMinus;
    JButton buttonTimes;
    JButton buttonDivide;

    JTextField expr;
    JButton buttonEquals;
    JTextField result;


    public Calculator()
    {
        ActionListener listener = new MyButtonListener();  //Use for ALL buttons.
        JFrame window = new JFrame("Calculator");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container content;
        content = window.getContentPane();
        content.setLayout( new BorderLayout() );


        JPanel bottomPanel = new JPanel();
        JPanel topPanel = new JPanel();
        JPanel ops = new JPanel();
        ops.setLayout(new GridLayout(4,3));
        JPanel digits = new JPanel();
        digits.setLayout(new GridLayout(4,1));

        button0 = new JButton("0");  //Generate and add buttons and listeners for bottomPanel
        digits.add(button0);
        button0.addActionListener(listener);
        button1 = new JButton("1");
        digits.add(button1);
        button1.addActionListener(listener);
        button2 = new JButton("2");
        digits.add(button2);
        button2.addActionListener(listener);
        button3 = new JButton("3");
        digits.add(button3);
        button3.addActionListener(listener);
        button4 = new JButton("4");
        digits.add(button4);
        button4.addActionListener(listener);
        button5 = new JButton("5");
        digits.add(button5);
        button5.addActionListener(listener);
        button6 = new JButton("6");
        digits.add(button6);
        button6.addActionListener(listener);
        button7 = new JButton("7");
        digits.add(button7);
        button7.addActionListener(listener);
        button8 = new JButton("8");
        digits.add(button8);
        button8.addActionListener(listener);
        button9 = new JButton("9");
        digits.add(button9);
        button9.addActionListener(listener);
        buttonCE = new JButton("CE");
        digits.add(buttonCE);
        buttonCE.addActionListener(listener);
        buttonC = new JButton("C");
        digits.add(buttonC);
        buttonC.addActionListener(listener);

        buttonPlus = new JButton("+");  //Generate operations buttons and add them
        ops.add(buttonPlus);
        buttonPlus.addActionListener(listener);
        buttonMinus = new JButton("-");
        ops.add(buttonMinus);
        buttonMinus.addActionListener(listener);
        buttonTimes = new JButton("*");
        ops.add(buttonTimes);
        buttonTimes.addActionListener(listener);
        buttonDivide = new JButton("/");
        ops.add(buttonDivide);
        buttonDivide.addActionListener(listener);


        expr = new JTextField(10);  //These will go on topPanel
        topPanel.add(expr);
        buttonEquals = new JButton("=");
        topPanel.add(buttonEquals);
        result = new JTextField(6);
        topPanel.add(result);

        bottomPanel.add(digits);
        bottomPanel.add(ops);

        content.add(bottomPanel, BorderLayout.SOUTH);  //Is this why it won't put them in a frame?
        content.add(topPanel, BorderLayout.NORTH);
        window.pack();
        window.setVisible(true);
    }

    public class MyButtonListener implements ActionListener
    {
        //Random bunch of if-else if statements for what happens when you
        //push each button.
        public void actionPerformed(ActionEvent e)
        {
            if (e.getSource() == button0)
            {
                expr.setText(expr.getText() + "0");
            }
            else if (e.getSource() == button1)
            {
                expr.setText(expr.getText() + "1");
            }
            else if (e.getSource() == button2)
            {
                expr.setText(expr.getText() + "2");
            }
            else if (e.getSource() == button3)
            {
                expr.setText(expr.getText() + "3");
            }
            else if (e.getSource() == button4)
            {
                expr.setText(expr.getText() + "4");
            }
            else if (e.getSource() == button5)
            {
                expr.setText(expr.getText() + "5");
            }
            else if (e.getSource() == button6)
            {
                expr.setText(expr.getText() + "6");
            }
            else if (e.getSource() == button7)
            {
                expr.setText(expr.getText() + "7");
            }
            else if (e.getSource() == button8)
            {
                expr.setText(expr.getText() + "8");
            }
            else if (e.getSource() == button9)
            {
                expr.setText(expr.getText() + "9");
            }
            else if (e.getSource() == buttonC)
            {
                expr.setText("");
                result.setText("");
            }
            else if (e.getSource() == buttonCE)
            {
                //clearLastEntry();
            }

            else if (e.getSource() == buttonPlus)
            {
                expr.setText(expr.getText() + "+");
            }
            else if (e.getSource() == buttonMinus)
            {
                expr.setText(expr.getText() + "-");
            }
            else if (e.getSource() == buttonTimes)
            {
                expr.setText(expr.getText() + "*");
            }
            else if (e.getSource() == buttonDivide)
            {
                expr.setText(expr.getText() + "/");
            }
            else if (e.getSource() == buttonEquals)
            {
                evaluate(expr, result);
            }

        }
    }
    /*private JTextField clearLastEntry(JTextField textbox)
    {
        textbox.setText(textbox.getText().substring(0, text.length()-1)); //Delete the last character.
        String text = textbox.getText();
        if (!(text.charAt(text.length()-1) == '+' || 
            text.charAt(text.length()-1) == '-' || 
            text.charAt(text.length()-1) == '*' ||
            text.charAt(text.length()-1) == '/')) return textbox;
        return clearLastEntry(textbox);
    }*/
    private void evaluate(JTextField expr, JTextField result)
    {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        //~~~Below is JavaScript code that will be run in Java.~~~~~
        //~~~It must be stored as a pure Object and manually ~~~~~~~
        //~~~converted to a String so it can be stored.  It ~~~~~~~~
        //~~~parses the arithmetic automatically, vastly ~~~~~~~~~~~
        //~~~simplifying the amount of code needed to be written. ~~
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

        try
        {
            Object textboxText = engine.eval(expr.getText());  //Store text as a pure object
            result.setText(textboxText.toString());
            expr.setText("");  //Blank out the text box.
        }
        catch (ScriptException e)
        {
            result.setText("Err");
            expr.setText("");
        }
    }

    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    //~The parsing method will throw the following~~//
    //~custom exception if the user does not input~~//
    //~~~~~~~~~~~valid calculator input.~~~~~~~~~~~~//

    /*private class TextNotArithmetic extends Exception
    {
        private TextNotArithmetic(JTextField textbox)  
        {
            char testChar;
            for (int i=0; i<textbox.getText().length()-1; i++)
            {
                testChar=textbox.getText().charAt(i);
                if (!(Character.isDigit(testChar) || testChar=='+' || testChar=='-' || 
                    testChar=='*' || testChar=='/'))  //if the character isn't valid
                {
                    throw new TextNotArithmetic();
                }
            }
        }
    }*/

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

And here's the block I'm asking about:

private void evaluate(JTextField expr, JTextField result)
    {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        //~~~Below is JavaScript code that will be run in Java.~~~~~
        //~~~It must be stored as a pure Object and manually ~~~~~~~
        //~~~converted to a String so it can be stored.  It ~~~~~~~~
        //~~~parses the arithmetic automatically, vastly ~~~~~~~~~~~
        //~~~simplifying the amount of code needed to be written. ~~
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

        try
        {
            Object textboxText = engine.eval(expr.getText());  //Store text as a pure object
            result.setText(textboxText.toString());
            expr.setText("");  //Blank out the text box.
        }
        catch (ScriptException e)
        {
            result.setText("Err");
            expr.setText("");
        }
    }

You can ignore most of my comments as some of them are outdated, but right now, my code compiles, but I don't get anything in my results box. Also, because I'm handing this in electronically and it'll be evaluated on a server, please do not make any suggestions to install additional packages. I figure Rhino should be enough, and as much as I hate eval, it seems to be the only way to do this, unless you guys have any other suggestions. Thank you!

share|improve this question
1  
Use the ScriptEngine. E.G. here. –  Andrew Thompson Jul 5 '13 at 2:18
    
Thanks! The only thing is that seems to be exactly what I have, only he declares the ScriptEngine and ScriptEngineManager elsewhere. –  Brandon Sherman Jul 5 '13 at 2:29
    
'he' being 'me'.. As suggested by StephenC - Change code of the form catch (Exception e) { .. to catch (Exception e) { e.printStackTrace(); // very informative! .. –  Andrew Thompson Jul 5 '13 at 2:31
    
Andrew, your code worked perfectly and I got a functional calculator app. It's just right now, my result field is blank. –  Brandon Sherman Jul 5 '13 at 2:42
    
I changed the catch, but I'm still not getting any output. –  Brandon Sherman Jul 5 '13 at 2:47

2 Answers 2

up vote 3 down vote accepted
    buttonEquals = new JButton("=");
    topPanel.add(buttonEquals);

Should be:

    buttonEquals = new JButton("=");
    buttonEquals.addActionListener(listener);  // add the listener!
    topPanel.add(buttonEquals);

Other tips

  • Change all instances of:
    else if (e.getSource() == button9)
    to
    else if (e.getSource().equals(button9)) // better compare using the method

  • See also this working example of using the ScriptEngine which uses some tricks to shrink around 260 LOC (e.g. the supplied code) to just 141 LOC. It does this by using loops to create the buttons, and (mostly) by using the button's action command directly (to add to the input).

share|improve this answer
1  
That was the issue. It always seems to be something obvious like that. Thanks! It's working fine now. –  Brandon Sherman Jul 5 '13 at 2:57
    
See also the edits. It includes tips on why your code (which is essentially the same as mine) can be shrunk from 260->140 LOC. :) –  Andrew Thompson Jul 5 '13 at 3:55

It is not immediately obvious to me what the problem is. But there is one thing you are definitely doing wrong that is going to make it harder to solve the problem ... unless you change it.

catch (ScriptException e)
    {
        result.setText("Err");
        expr.setText("");
    }

This is not helpful. If a scripting exception occurs, you are catching it, throwing away all the information about what went wrong. At the very least, you should print or log an exception stacktrace somewhere.

share|improve this answer
    
Thanks! I just changed that catch block to: catch (ScriptException e) { e.printStackTrace(); //result.setText("Err"); //expr.setText(""); } But I'm still getting the same error. –  Brandon Sherman Jul 5 '13 at 2:38
    
//result.setText("Err"); There is no harm in doing those things in addition to calling printStackTrace() that (or logging) is simply a good addition to any existing user feed-back. Though you might experiment with setText(e.getMessage()) for quick warning of things like divide by 0 error.. –  Andrew Thompson Jul 5 '13 at 3:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.