Ter uma ação diferente para cada botão criado dinamicamente em um loop
-
19-09-2019 - |
Pergunta
Use muito este site, mas a primeira vez postar. Meu programa cria vários botões, dependendo do número de registros em um arquivo. Por exemplo, 5 registros, 5 botões.
Os botões estão sendo criados, mas estou tendo um problema com o ouvinte de ação.
Se adicionar o ouvinte de ação no loop, cada botão faz a mesma coisa; Mas se eu adicionar o ouvinte de ação fora do loop, ele apenas adicionar o ouvinte de ação ao último botão.
Alguma ideia?
Aqui está o que tenho em termos de código (acabei de adicionar o loop for para economizar espaço):
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++;
}
Muito apreciado
Solução
Ao criar um ouvinte de ação para cada botão que você está criando, você pode ter isso:
final int buttonIndex = i;
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae2) {
System.out.println("Button pressed is: " + buttonIndex);
}
}
Para acessar uma variável dentro de um método de classe anônima, ele deve ser marcado final. É isso que você tem isso final int buttonIndex = i;
declaração.
Você pode usar o setActionCommand
método no botão para definir um comando de ação para ele que você poderia recuperar do ActionCommand propriedade do ActionEvent
classe. Ao fazer isso, você pode ter o mesmo ouvinte para todos os seus botões. Você pode definir esse comando de ação para o buttonIndex
variável que eu defini no seu exemplo. Ao fazer isso, você cria uma classe menos anônima em seu aplicativo, o que é sempre bom (menos objetos que consomem menos memória).
Outras dicas
Você pode adicionar a referência e o índice do botão (i
) de cada botão para um mapa de hash enquanto os cria.
No seu ouvinte One Action, você pode procurar o índice do botão que adquiriu o evento no seu hashmap pela referência do botão.
Algo assim (pseudo código, então por favor não me vote se não compilar):
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++;
}
Por que não configurar seus listadores de ação fora do loop e fazer uma matriz deles, onde o índice do ActionListener em seus ouvintes corresponde a qual botão é adicionado. Algo assim:
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]);
}
Aviso, porém, não testei este código.
Seu primeiro problema reside com a dependência da variável j
.
Você está atribuindo todos os botões exatamente o mesmo ActionListener, que imprimiria o objeto no índice j
, que na época os botões são exibidos é == o último índice da lista no momento dos incrementos, da lista 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();
}
});
}
}
}