0

I want to center the content of the JTextField based on its content.

     for(int i=0; i<10; i++){                                   
           txtFields[i] = new JTextField(20); 

           txtFields[i].addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    txtFields[i].setHorizontalAlignment(JTextField.CENTER);
                }
            });
        }

I am getting error, local variable i cannot be accessed within innerclass.

Cœur
  • 37,241
  • 25
  • 195
  • 267
AGEM
  • 217
  • 2
  • 5
  • 12

3 Answers3

4

This is because the variable i is not available in the scope that actionPerformed is called. A simple fix would be to declare a final variable in the for loop's scope:

for (int i = 0; i < 10; i++) {    
    final JTextField currentField = new JTextField(20);                               
    txtFields[i] = currentField;
    txtFields[i].addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
             currentField.setHorizontalAlignment(JTextField.CENTER);
         }
    });
}

Or:

for (int i = 0; i < 10; i++) {                             
    txtFields[i] = new JTextField(20);
    txtFields[i].addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
             ((JTextField) e.getSource()).setHorizontalAlignment(JTextField.CENTER);
         }
    });
}

Personally, I'd suggest you create an ActionListener subclass that accepts a JTextField in its constructor. It's a cleaner approach and helps reduce confusing defects like the one you encountered.

Marc Baumbach
  • 10,323
  • 2
  • 30
  • 45
  • What if he/she declare `i` outside the for loop. Will that work? – Smit Jan 14 '13 at 23:32
  • 1
    @smit No, it's still not in the right scope. It will also have the value of `9` after the loop is done anyway, which would mean that anytime actionPerformed is called on any of the `ActionListener` it would attempt to set the horizontal alignment on `txtFields[9]`. – Marc Baumbach Jan 14 '13 at 23:38
  • I am still dubious. You could be right. Will have to try in free time. – Smit Jan 14 '13 at 23:47
  • 1
    The reason is because an anonymous inner class, the `ActionListener`, only has access to variables inside of itself as well as any `final` variables declared/available in the scope containing the anonymous inner class. More info here if you're interested: http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class – Marc Baumbach Jan 14 '13 at 23:50
  • 1
    @HovercraftFullOfEels and +1 mbaumbach. Thanks for updates and link. – Smit Jan 14 '13 at 23:55
1

Just before the "addActionListener" statement write "final int j = i;", and then use "j" within the inner class.

gcvt
  • 1,482
  • 13
  • 15
1

Why the ActionListener at all? Perhaps I'm misunderstanding your requirement, but won't this do what you're looking for:

for (int i=0; i<10; i++)
{                                   
  txtFields[i] = new JTextField(20);
  txtFields[i].setHorizontalAlignment(JTextField.CENTER);
}
splungebob
  • 5,357
  • 2
  • 22
  • 45