7

I have something like the code below:

    for(int i=0;i<10;i++){
        button=new JButton(buttons[i]);
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                setPage(i);
            }
        });
        menu.add(button);
    }

However, the variable i isn't defined in the scope of the ActionListener class. How can I pass the variable?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Leo Jiang
  • 24,497
  • 49
  • 154
  • 284

3 Answers3

22

A totally different approach would be to add a property to the button, and retrieve that property in your action listener. E.g.

button=new JButton(buttons[i]);
button.putClientProperty( "page", i );
button.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e) {
      setPage((Integer)((JButton)e.getSource()).getClientProperty( "page" ));
   }
});
Robin
  • 36,233
  • 5
  • 47
  • 99
  • This should be the accepted answer. It's a simpler approach. Frankly, I didn't know that properties can be added to buttons like that. Great answer. – Akshay Damle Aug 12 '15 at 11:31
  • Maybe the asker decided to not use an anonymous class anymore so he accepted the answer by JB Nizet instead. – Xel Nov 25 '16 at 05:04
  • What if you are using a class that doesn't have "putClientProperty()"? Such as javax's Timer. – Markus Tonsaker Mar 09 '17 at 07:49
21

In addition to Hovercraft's answer, you should note that you're not forced to use anonymous classes for your listeners. The code of Hovercraft's answer is similar to the following one:

private class PageActionListener implements ActionListener {
    private int page;

    public PageActionListener(int page) {
        this.page = page;
    }

    public void actionPerformed(ActionEvent e) {
        setPage(page);
    }
}

...

for(int i = 0; i < 10; i++){
    button = new JButton(buttons[i]);
    button.addActionListener(new PageActionListener(i));
    menu.add(button);
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I like this approach, more then making a final variable in the loop (personal preference of course). A +1 to correct the downvote – Robin Jun 14 '12 at 18:44
13

The variable i is in fact in the scope of the ActionListener, but since you're trying to use a local variable in an inner class, the variable must be final. So, you could use a final variable for this:

for(int i=0;i<10;i++){
    final int index = i;
    button=new JButton(buttons[i]);
    button.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            setPage(index);
        }
    });
    menu.add(button);
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373