1

Trying to create action listeners to perform multiplication tasks. It seems to work, however it seems to ignore my last digit entered. I keep thinking I need a second variable to keep track of last command so that when the equal button is pressed it adds the current digit to the previous ones. But then I wouldn't I have to perform the task if the equal button is pressed?

class ButtonListener implements ActionListener {        
    public void actionPerformed(ActionEvent e) {
        String numbers = e.getActionCommand();
        if (begin) {
            textField.setText(numbers);
            begin = false;
        }

        else if (numbers.equals("C")) {
            textField.setText("0.0");
            action.reset();
        }

        else 
            textField.setText(textField.getText() + numbers);
    }
}

class OperatorListener implements ActionListener {  

    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        String text = textField.getText();

        if (begin) {
            textField.setText("0.0");
            action.setTotal("0.0");
        }
        else {
            if (command.equals("+")) {
                action.add(text);
                begin = true;
            }
            else if (command.equals("=")) {
                textField.setText(text);
                System.out.println(action.getTotal());
            }
            textField.setText(action.getTotal());
        }
    }
}

Some explanation of variable. begin simply checks if the current state of the JTextField is blank or not. action is simply the method to "add", it has other calls I want it to do.

Any suggestions on how to keep track of last command or get around so it doesn't ignore the last digit? These tasks are similar to those of a calculator.


EDIT: For those interested, here is what I ended up with.

class ButtonListener implements ActionListener {        
    public void actionPerformed(ActionEvent e) {
        String numbers = e.getActionCommand();

        // check if a number has been pressed
        if (begin) {
            textField.setText(numbers);
            begin = false;
        }

        // if clear is checked
        else if (numbers.equals("C")) {
            action.reset();
            begin = true;
            operator = "=";
            textField.setText("0.0");
        }

        // Once a number is pressed keep adding it to the text field until an operator is pressed

        else 
            textField.setText(textField.getText() + numbers);
    }
}

/**
 * Action listener for Operators
 */

class OperatorListener implements ActionListener {  

    public void actionPerformed(ActionEvent e) {
        // String command = e.getActionCommand();

        // if nothing has been pressed
        if (begin) {
            textField.setText("0.0");
            begin = false;

        // else begin performing operation pressed
        } else {
            begin = true; 
            String text = textField.getText();

            // right away add the value of the text field
            if (operator.equals("=")) {
                action.setTotal(text);
            } 
            else if (operator.equals("+")) {
                action.add(text);
            } 
            // and so on for all the other operators.

            textField.setText("" + action.getTotal());

            // now capture the operator pressed.
            operator = e.getActionCommand();
        }
    }
}
fernan
  • 34
  • 3
  • 7
  • 1
    for Number instance only JFormattedTextField http://download.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html as here suggested – mKorbel Aug 05 '11 at 06:24
  • Umm.. `ActionListener` is AWT, not Swing. – Andrew Thompson Aug 05 '11 at 07:07
  • @Andrew: Well, ActionListener is in the AWT package, but JButton has an addActionListener functino which takes an ActionListener as a parameter, so apparently the inventors of Java expect you to use it in Swing programs. That's how I almost always handled button clicks (back when I wrote Swing programs). Do you have a different method? – Jay Aug 05 '11 at 20:07
  • @Jay & Andrew: I'm curious about the apparent loss of the "last digit entered." Of possible relevance: "How the text field consumes `VK_ENTER` events depends on whether the text field has any action listeners."—[JTextField](http://download.oracle.com/javase/6/docs/api/javax/swing/JTextField.html). @fernan: I think we need more context, preferably an [sscce](http://sscce.org/). – trashgod Aug 05 '11 at 21:15
  • I was trying to stay away from JFormattedTextField as I'm later going to add Strings t o my buttons. Andrew & Jay; I do have JButtons, so why I had this listed as swing vs AWT. Have some numbers that I want to be able to do simple math, such as add, divide, multiply and subtract. Later I will do other things with the other buttons. trashgod; I can post sscce later as dont have code with me. – fernan Aug 05 '11 at 22:16
  • @Jay *"Do you have a different method?"* Sure. I don't recommend it, but some people add a `MouseListener` to buttons. That is also AWT, in case anyone is confused. But then my point is that if the main focus of a problem is `BorderLayout`, flag the post as AWT. If `BoxLayout`, Swing. In this case, you could probably swap out the `JTextField` for a `TextField` to see the same effect, so the GUI components are **not** the main point, it is the **listeners that matter.** – Andrew Thompson Aug 06 '11 at 06:00

2 Answers2

1

Side note: In general it's easier to make a separate listener for each button, rather than trying to share a listener. When you make one listener, then you're first funnelling several buttons to one function, and then requiring that function to separate them out. Why not just keep them separate to begin with? If there's common code, call a common function.

But to your question: If all operators have equal precedence, then just save the operator. As in:

class Calculator
{
  // Well, this would probably better be an enum, but whatever.
  public char operator=' ';
  public float lastNum;

  public void calc()
  {
    try
    {
      double currNum=Double.parseDouble(numfield.getText());
      if (operator==' ')
        lastNum=currNum;
      else if (operator=='+')
        lastNum+=currNum;
      else if (operator=='-')
        lastNum-=currNum;
      else if (operator=='*')
        lastNum*=currNum;
      else if (operator=='/')
        lastNum/=currNum;
    }
    catch (NumberFormatException panic)
    {
      ... whatever error handling ...
    }
  }
}
class OperatorListener implements ActionListener
{
   Calculator calc;
   public OpeatorListener(Calculator calc)
   {
     this.calc=calc;
   }
   public abstract void actionPerformed(ActionEvent e);
}
class PlusListener extends OperatorListener
{
  public void actionPeformed(ActionEvent e)
  {
    calc.calc();
    calc.operator='+';
  }
}
class MinusListener extends OperatorListener
{
  public void actionPerformed(ActionEvent e)
  {
    calc.calc();
    calc.operator='-';
  }
}
class EqualListener extends OperatorListener
{
  public void actionPerformed(ActionEvent e)
  {
    calc.calc();
  }
}

This code gives equal precedence to all operators, e.g. "2+3*5=" would give 25.

If you want multiplication and division to have higher precedence, e.g. "2+3*5=" gives 17, you'd need to create a stack and hold operators and temporary intermediate values and some other complexity.

Jay
  • 26,876
  • 10
  • 61
  • 112
  • shouldn't you be casting (float)? `if (operator==' ') lastNum= (float) currNum;` etc.. I guess i fail to connect how it is going to solve the problem. But I will try it. – fernan Aug 05 '11 at 22:30
  • Whoops, I switched from using floats to using doubles in the above code for no apparent reason. It should be consistent. Anyway, the point of the above code -- and I suppose I should have spelled this out, otherwise it's just a mass of code -- is that when the user clicks on an operation, you should read the textbox and save the value and the operation. When the user clicks on the equals, you should read the textbox again, to get the second number, then perform the saved operation on the first and second values. – Jay Aug 07 '11 at 03:25
  • And if you want to allow running calculations, like 1+2+3=, you need to calculate and save an intermediate value each time an operation is clicked, provided there is a previous running value. – Jay Aug 07 '11 at 03:26
  • I ended up using something similar to your suggestion, added it above. Thank you. – fernan Aug 10 '11 at 16:55
1

As you are storing operands in a JTextField, it may be convenient to listen for property changes, document changes, or focus changes in order to decide what action to take.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • The original post does not specify the UI. I was assuming that it consisted of a text box to enter the numbers and a set of buttons for +, -, *, /, =, and maybe other operations. Given that assumption, you should process the text box when and only when a button is clicked. Of course the OP might have had some other UI in mind, and even if he didn't other UI's are certainly possible. – Jay Aug 05 '11 at 20:03
  • @Jay: My thoughts exactly; absent more context in the question, I intended my suggestions as complementary to your approach. – trashgod Aug 05 '11 at 21:03