Question

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

Was it helpful?

Solution

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).

OTHER TIPS

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++;
}

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.

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.

public class Scroll_view extends Activity {

Button btn;
Button btn1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scroll_view);



        LinearLayout linear=(LinearLayout)findViewById(R.id.linear);
        for(int i=1; i<=20 ;i++){
            LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
            btn=new Button(this);
            btn.setId(i);
            final int id_=btn.getId();
            btn.setText("button " + id_);
            linear.addView(btn,params);


            btn1=((Button)findViewById(id_));
            btn1.setOnClickListener(new View.OnClickListener(){         
                public void onClick(View view){
                    Toast.makeText(view.getContext() , "Button clicked index = " + id_ , Toast.LENGTH_SHORT).show();
                }
                });
               }
            }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top