views:

224

answers:

4

Hi, use this website a lot but first time posting. My program creates a number of buttons depending on the number of records in a file. E.g. 5 records, 5 buttons.

The buttons are being created but i'm having a problem with the action listener.

If add the action listener in the loop every button does the same thing; but if I add the action listener outside the loop it just adds the action listener to last button.

Any ideas?

Here is what I have code-wise (I've just added the for loop to save space):

int j=0;
for(int i=0; i<namesA.size(); i++)
{
    b = new JButton(""+namesA.get(i)+"");
    conPanel.add(b);
    conFrame.add(conPanel);

    b.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae2){

                System.out.println(namesA.get(j));

        }
    }});
    j++;
}

Much Appreciated

A: 

Why not setup your ActionListeners outside the loop and make an array of them, where the index of the actionListener in your listeners array corresponds to which button it gets added to. Something like this:

ActionAdapter[] listeners = new ActionAdapter[namesA.size()];
//fill listeners with ActionAdapters
listeners[0] = new ActionAdapter() 
{
    public void actionPerformed(ActionEvent e) {
        //Do stuff
    }
};
//Repeat for each button you need

for(int i = 0; i < namesA.size(); i++)
{
    b = new JButton("" + namesA.get(i) + "");
    conPanel.add(b);
    b.addActionListener(listeners[i]);
}

Warning though, I haven't tested this code.

Corey Sunwold
That is great. Thanks but I still have a problem with filing the listeners as it is unknown how many buttons are needed...could be 5.. could be 100
Oliver
A: 

You could add the button reference and index (i) of each button to a hash map as you're creating them.

In your one action listener, you can look up the index of the button that sourced the event in your hashmap by its button reference.

Something like this (pseudo code, so pls don't downvote me if it doesn't compile):

Hashmap<JButton, Integer> map = new Hashmap<JButton, Integer>();

int j=0;
for (int i = 0; i < namesA.size(); i++)
{
    b = new JButton("" + namesA.get(i) + "");
    conPanel.add(b);
    conFrame.add(conPanel);

    // Add a mapping
    map.add(b, new Integer(i));

    b.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae2) {
            // Look up the button in the map, and get it's index
            Integer index = map.get( ae2.getSource() );

            // Do something different here based upon index
        }
    });
    j++;
}
Scott Smith
A: 

As you are creating one action listener for each button that you are creating, you could have this:

final int buttonIndex = i;
b.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent ae2) {
       System.out.println("Button pressed is: " + buttonIndex);
   }
}

To access a variable inside an anonymous class method, it has to be marked final. That's what you have that final int buttonIndex = i; statement.

You can use the setActionCommand method on the button to define an action command to it that you could retrieve from the actionCommand property of the ActionEvent class. By doing that, you could have the same listener for all your buttons. You could set that action command to the buttonIndex variable that I defined in your example. By doing that, you create less anonymous class in your application, which is always good (less objects consuming less memory).

Ravi Wallau
This works like a treat! Thank you very much.
Oliver
A: 

Your first problem resides with the reliance on variable j.

You're assigning all of the buttons the exact same ActionListener, which would print out the object at index j, which at the time the buttons are displayed is == the last index of the list at the time of the increments, of List namesA.

Kavon Farvardin