Avere un'azione diversa per ogni pulsante creato in modo dinamico in un ciclo
-
19-09-2019 - |
Domanda
utilizzare questo sito molto, ma primo incarico volta. Il mio programma crea una serie di pulsanti a seconda del numero di record in un file. Per esempio. 5 record, 5 pulsanti.
I pulsanti sono stati creati ma sto avendo un problema con il listener di azione.
Se aggiungere l'ascoltatore azione nel ciclo ogni bottone fa la stessa cosa; ma se aggiungo il listener di azione al di fuori del ciclo aggiunge solo l'ascoltatore azione da ultimo pulsante.
Tutte le idee?
Ecco quello che Ho codice-saggio (Ho appena aggiunto il ciclo for per risparmiare spazio):
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++;
}
Molto apprezzato
Soluzione
Come si crea un listener di azione per ogni pulsante che si sta creando, si potrebbe avere in questo modo:
final int buttonIndex = i;
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae2) {
System.out.println("Button pressed is: " + buttonIndex);
}
}
Per accedere a una variabile all'interno di un metodo di una classe anonima, deve essere marcata finale. Questo è quello che si ha questa affermazione final int buttonIndex = i;
.
È possibile utilizzare il metodo setActionCommand
sul pulsante per definire un comando di azione ad esso che si potrebbe recuperare dal actionCommand proprietà della classe ActionEvent
. Così facendo, si potrebbe avere lo stesso listener per tutti i pulsanti. È possibile impostare che l'azione di comando alla variabile buttonIndex
che ho definito nel tuo esempio. Così facendo, si crea una classe meno anonimi nella vostra applicazione, che è sempre bene (meno gli oggetti che consumano meno memoria).
Altri suggerimenti
Si potrebbe aggiungere il riferimento tasto e l'indice (i
) di ciascun pulsante a una mappa di hash come si sta creando loro.
Nel vostro un ascoltatore di azione, è possibile cercare l'indice del pulsante di provenienza l'evento nella vostra hashmap dal suo riferimento pulsante.
Qualcosa di simile (pseudo codice, in modo pls non mi downvote se non compila):
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++;
}
Perché non di impostazione tuoi ActionListeners al di fuori del ciclo e fare una serie di loro, dove l'indice del ActionListener nella propria matrice ascoltatori corrisponde al tasto cui viene aggiunto. Qualcosa di simile a questo:
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]);
}
Attenzione, però, non ho testato questo codice.
Il primo problema risiede con la dipendenza da j
variabile.
Si sta assegnando tutti i pulsanti esattamente lo stesso ActionListener, che stampare l'oggetto di indice j
, che al momento vengono visualizzati i pulsanti è == l'ultimo indice della lista, al momento degli incrementi, della 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();
}
});
}
}
}