Search code examples
javaloopsswingjbuttonactionlistener

JButton ActionListeners different variable in each loop


I am making a simple calculator using a JFrame and JButtons. Before I made each button, 0 thru 9, with their own action listeners, now I have realized that this is super inefficient and I should use a loop to make each button and assign the ActionListeners. So the only thing that needs to happen in each ActionListener is to add whatever number the button is to a JTextField, called nums. Here is what I have now.

for(int i = 0; i <=9; i++) {
        count = i;
        btns.get(i).addActionListener(new ActionListener(){ //makes action listeners for each button
            public void actionPerformed(ActionEvent e){ 

                    nums.setText(nums.getText()+ count);//IMPORTANT CODE

            }       
        });
      }

So as you can see I used a terribly named variable named count. count is set to i in each iteration before the important code is used. I have to do this because an AL is it's own class and cannot access i. However count is public and static, so the ALs can use count.

My problem is that all the buttons print 9. This logically makes sense because what is happening is that the ALs in each button use the count variable, when the loop is done, count will be 9, which means each AL will essentially contain nums.setText(nums.getText()+ 9);. Instead, I need button 1 to be nums.setText(nums.getText()+ 1); 2 to be 2, ETC.

I have tried to call the text of each button, however, because you need to use an index in the ArrayList get method, you need a variable, if you use count, the same problem occurs; after the for loops has terminated, count is 9, so all the buttons print the text of the 9 button.

Any and all help is appreciated, Thanks in advance, -Max

P.S. Just in case you don't understand why I'm getting the text and then adding count, it is because in order to type the number 12. you need to type 1 and then concatenate the 2 to the one to et 12. getText gets the 1, and adding count concatenates the 2 to make 12.


Solution

  • In general you will want to avoid using static fields as you loose all benefits of object-oriented programming by this. There are specific places for use of static fields, but this is not one of them. In your situation you can't use the index of the loop, i, directly since it is not a final local variable, and non-final local variables cannot be used within anonymous inner classes. So a simple solution exists:

    Make count a final local variable and you should be able to use it within your anonymous inner class:

    for(int i = 0; i <= 9; i++) {
        final int finalCount = i;
        btns.get(i).addActionListener(new ActionListener(){ 
            public void actionPerformed(ActionEvent e){ 
    
                nums.setText(nums.getText() + finalCount);
    
            }       
        });
    }