Sergey. A
Sergey. A

Reputation: 15

How to create N ActionListener with for loop?

I have been created N(unknown SIZE) Jbuttons with for loop and placed them in the frame. I am trying to display the message "Button number x" by clicking on button number x. On the second for loop, when I trying to create N ActionListener I have some error.

Error

Local variable I defined in an enclosing scope must be final or effectively final

Code

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class program extends JFrame{
    final int N = 10;
    final int JUMPS = 210;
    private JButton[] buttons = new JButton[N];

    public program(){
        super("test");
        setLayout(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        for (int i = 0; i < N; i++) {
            buttons[i] = new JButton("" + i);
            buttons[i].setBounds((i % 4) * JUMPS, (i / 4) *JUMPS , 200, 200);
            add(buttons[i]);
        }

        for (int i = 0; i < N; i++) {
            buttons[i].addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(null, "Button number " + i);
                }
            });
        } 

        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        program mainGUI = new program();
    }
}

Did you have any solution for the error?

Upvotes: 1

Views: 1788

Answers (3)

khelwood
khelwood

Reputation: 59104

You can't reference a local variable i inside your ActionListener implementation unless i is final (or effectively final). But you can just make a final variable and reference that.

for (int i = 0; i < N; i++) {
    final int final_i = i;
    buttons[i].addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            JOptionPane.showMessageDialog(null, "Button number " + final_i);
        }
    });
} 

And in Java 8 you can do this more consisely:

for (int i = 0; i < N; i++) {
    final int final_i = i;
    buttons[i].addActionListener(e ->
       JOptionPane.showMessageDialog(null, "Button number " + final_i)
    );
} 

Upvotes: 1

Selmi Karim
Selmi Karim

Reputation: 2235

If anonymous class is created inside any method then all the local variables defined in the method but outside the body of the anonymous class should be made final in case they are needed to be used in anonymous class.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class program extends JFrame{
    final int N = 10;
    final int JUMPS = 210;
    private JButton[] buttons = new JButton[N];

    public program(){
        super("test");
        setLayout(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        for (int i = 0; i < N; i++) {
            buttons[i] = new JButton("" + i);
            buttons[i].setBounds((i % 4) * JUMPS, (i / 4) *JUMPS , 200, 200);
            add(buttons[i]);
        }

        for (int i = 0; i < N; i++) {
        final int buttonNumber = i ;
            buttons[i].addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(null, "Button number " + buttonNumber);
                }
            });
        } 

        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        program mainGUI = new program();
    }
}

Upvotes: 0

Reimeus
Reimeus

Reputation: 159754

You could do

JOptionPane.showMessageDialog(null, "Button number " + e.getActionCommand());

Upvotes: 2

Related Questions