0

Before explaining, here's the code:

public class Calculator extends JFrame implements ActionListener {
    private String[] ops = { "+", "-", "*", "/", "=" };
    private JButton[] buttons = new JButton[16];
    private JTextField field;

    private int currentAnswer;

    public Calculator() {
        super("Calculator");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new GridBagLayout());
        addComponents();
        pack();
        setLocationRelativeTo(null);
    }

    private void addComponents() {
        GridBagConstraints gbc = new GridBagConstraints();

        field = new JTextField(10);
        add(field, gbc);

        gbc.gridy++;

        add(buttons[0] = newButton("0"), gbc);
        add(buttons[10] = newButton("+"), gbc);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String text = field.getText();

        /* Checks for operation chars */
        for(int i = 0; i < ops.length; i++) {
            if(text.endsWith(ops[i])) {
                field.setText("");
                System.out.println("called");
                break;
            }
        }

        /* Checks if number was pressed */
        for (int i = 0; i <= 9; i++) 
            if (e.getSource() == buttons[i]) {
                field.setText(text + buttons[i].getText());
                return;
            }

        switch (e.getActionCommand()) {
            case "+":
                currentAnswer += Integer.parseInt(text);
                field.setText(text + e.getActionCommand());
                return;
        }
    }

    public JButton newButton(String name) {
        JButton newButton = new JButton(name);
        newButton.addActionListener(this);
        return newButton;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                Calculator calculator = new Calculator();
                calculator.setVisible(true);
            }
        });
    }
}

My goal is to check if my JTextField field contains a math operator (which I have stored in a String array). If it does, "clear" the text field before moving on.

The problem is: My program is telling me the code has been executed ("called" prints out), yet my results show as if setText("") was never called.

I did initialize all my components (and my frame) on the EDT. If you need to see the rest of the code, let me know (it's not much). A friend of mine sent me this, and I was trying to clean it up (iron out the bugs). I'm not sure if it's just a little thing I'm not seeing, but I know Swing has a lot of "rules", and it's really hard to keep up with it all /:


EDIT:

After pressing the "+" button, this is what happens when i press a number button afterwards

String text = field.getText(); 
System.out.println(text); // prints "0+" like expected (after pressing number)

/* Checks for operation chars */
for(int i = 0; i < ops.length; i++) {
    if(text.endsWith(ops[i])) {
        field.setText("");
        System.out.println("called"); //gets printed
        break;
    }
}

System.out.println(text); //even when "called" prints, text is not ""

Why is it not clearing? :s

Vince
  • 14,470
  • 7
  • 39
  • 84
  • 1
    Post [**`SSCCE`**](http://sscce.org/) – PM 77-1 May 29 '14 at 01:36
  • Consider providing an actual [runnable example that demonstrates your problem](https://stackoverflow.com/help/mcve) would involve less guess work and better responses – MadProgrammer May 29 '14 at 01:36
  • As is all too common, you aren't telling quite enough about your problem "As if setText("") was never called" doesn't tell us what DOES happen. Is there other text? Different text? Are you trying to clear it before something else shows up, even if what is supposed to show up in one of the setText() calls later in that method? What? – arcy May 29 '14 at 01:37
  • text.endsWith(ops[i]): make sure your text doesn't end with a space or something like it. Consider using indexOf – Alexandre Santos May 29 '14 at 01:41
  • @MadProgrammer Updated my answer. Sorry about that – Vince May 29 '14 at 01:43

1 Answers1

3

There are a couple of problems...

First, your actionPerformed method is doing exactly what you told it to

for (int i = 0; i < ops.length; i++) {
    if (text.endsWith(ops[i])) {
        field.setText("");
        System.out.println("called");
        break;
    }
}

/* Checks if number was pressed */
for (int i = 0; i <= 9; i++) {
    if (e.getSource() == buttons[i]) {
        // Here, the field text is been rest to text + button.text...
        field.setText(text + buttons[i].getText());
        // And nothing will be executed after it...
        return;
    }
}

So, even if the field is cleared, it will always be set back to the existing value plus the value of the button's text...

What I "think" you want to do, is calculate the value of the field first, then process the button press...

Updated based on edits

// You assign the reference to the `String` maintained by the text field...
String text = field.getText(); 
System.out.println(text); // prints "0+" like expected (after pressing number)

/* Checks for operation chars */
for(int i = 0; i < ops.length; i++) {
    if(text.endsWith(ops[i])) {
        // You assign a NEW reference to the text field, this
        // won't change the contents of text as they are different
        // references...
        field.setText("");
        System.out.println("called"); //gets printed
        break;
    }
}

// text has not changed, this variable and the field contents are not
// magically linked
System.out.println(text); //even when "called" prints, text is not ""

Also, remember, String in Java is nonmutable, meaning that once created, a Strings contents can't be changed, it can simply be reassigned...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • That was a problem on my part (by minimizing the code). The "+" button uses `buttons[11]`, so it doesn't trigger the condition in the loop `if(e.getSource() == buttons[i])` in my original code. Let me fix that up – Vince May 29 '14 at 01:58
  • You still have the same problem in your `switch` statement `field.setText(text + e.getActionCommand());`.... – MadProgrammer May 29 '14 at 02:00
  • But the switch statement case only triggers when I press "+". Every time a button is pressed, it first checks for operators. If there is one, clear the field, THEN start adding numbers. But it's as if it's skipping the clearing stage. The field should clear (then be set to "0" or whatever number) right away if the current text sends with an operator. The switch statement case is to add the operator at the end of my field's text when an operator button is pressed. It doesn't trigger in the same method call as when `"called"` prints – Vince May 29 '14 at 02:12
  • But, you've kept a reference of what WAS in the text field and then you're ADDING that back in... – MadProgrammer May 29 '14 at 02:13
  • There's also an `NumberFormatException` been thrown when you try and do `currentAnswer += Integer.parseInt(text)` – MadProgrammer May 29 '14 at 02:14
  • Actually, I thought I understood it (was at my phone), but once I went back to my computer to check some things out, it's still confusing me.. I'll edit my answer with whats confusing me. I'm sorry – Vince May 29 '14 at 02:18
  • I have updated my question; please take the time to check it out. I'm sorry if the solution is flying right over my head – Vince May 29 '14 at 02:28
  • Oh wow, and the stupidity sinks in... Thanks a ton man, I completely see what I did wrong now – Vince May 29 '14 at 02:50
  • 1
    Welcome to the forest, watch out for the trees ;) – MadProgrammer May 29 '14 at 02:56