Hallo,
erstmal nette Grüße an alle, als Neuling im Forum :bae:.
Ich habe ein Problem beim Zuordnen von ActionListenern zu Buttons.
Die Buttons habe ich als Array definiert und will jedem nun in der for-Schleife jeweils eine eigene Methode zuordnen die sich im Objekt AktionsListener befinden. Dabei haben die Methoden den Namen actionX(), wobei X für die Nummer des Buttons geht. Ich habe es jetzt schon ewig versucht hin zu bekommen und habe dazu unter anderem schon probiert es nach diesem Thread zu lösen: http://www.java-forum.org/de/viewtopic.php?p=240462. Hieraus habe ich den Code der zwischen "new ActionListener()" steht abgeleitet.
Mittlerweile bin ich jetzt so weit dass ich das i nicht erst in den Klammern von for erzeuge, sondern schon vorher. Das hat ein Problem gelöst das mir Eclipse zeigte, dass ich keine Variablen einer äußeren Methode von einer inneren aus aufrufen darf, außer sie ist als final deklariert.
Ich müsste jetzt im Moment nur noch dieses m irgendwie so umwandeln dass es als Pfad zu der Methode akzeptiert wird. Oder wäre eine andere Lösung sinnvoller?
Viele Grüße,
Thomas
Fensta.java
Code:
private int i;
private Button bu[] = new Button[19];
private AktionsListener al = new AktionsListener(this);
public Fensta() {
for (i = 0; i <= 18; i++) {
bu[i] = new Button();
bu[i].addActionListener(new ActionListener(){
Method[] methods = al.getClass().getMethods();
public void actionPerformed(ActionEvent e){
String m= al+"."+methods[i].getName();
//Hier sollte m als Aufruf der zugehörigen Methode hin (Bsp.: bu[0] ruft action0 in AktionsListener auf).
}
});
}
}
AktionsListener.java
Code:
private Fensta f;
public AktionsListener(Fensta f) {
this.f=f;
}
//Aktionen
public void action0(ActionEvent e) {
}
public void action1(ActionEvent e) {
}
public void action2(ActionEvent e) {
}
public void action3(ActionEvent e) {
}
public void action4(ActionEvent e) {
}
public void action5(ActionEvent e) {
}
.
.
.
usw.
Meine Lösungsansatz war leicht falsch. So sieht meine for-Schleife jetzt aus und erfüllt den gewünschten Zweck, dass jeder Button eine eigene Methode zugewiesen bekommt die bei einer "action" ausgeführt wird (fällt mir erst jetzt ein die Formulierung, hätte euch glaub von Anfang an am meisten geholfen, sorry).
Code:
for (i = 0; i <= 18; i++) {
bu[i] = new Button();
bu[i].addActionListener(new ActionListener(){
Method met = al.getClass().getMethod("action"+i, ActionEvent.class);
public void actionPerformed(ActionEvent e){
try {
met.invoke(al, e);
}
catch (IllegalArgumentException e1) {}
catch (IllegalAccessException e1) {}
catch (InvocationTargetException e1) {}
}
});
}
Die Exception-Blöcke habe ich frei gelassen, da bei einem Button den man nur drücken - oder nicht drücken - kann nicht wirklich was schief laufen könnte.
In fast allen Fällen ist diese Vorgehensweise absoluter Unsinn.
Ich biete dir nochmal an das du beschreibst was du haben möchtest und dann kann man über eine sinnvolle Lösung nachdenken.
Also ich versuch grad für mich zum Üben einfach mal einen einfachen Taschenrechner zu programmieren. Bin jetzt in der 11 Klasse und lerne dort mein erstes Jahr Java.
Ich weis nicht in welchem Hinblick du es als absoluten Unsinn bezeichnest, die Buttons als array zu definieren (sagt der Lehrer würden wir später eh immer so machen...), allgemein oder irgendwie anders. Dies ist meine Lösung aus meinem bisherigen Wissen und dem wo ich mit Suchen und Interpretieren zusammen bekommen habe :###.
In der Schule haben wir es bisher immer so gemacht dass wir ein Hauptprogramm mit der main-Methode erstellt haben. Bei mir ist das mittlerweile einfach Haupt.java. Dann ein neues Objekt in dem wir das Fenster erstellen liesen, bei mir Fensta.java und jeweils ein Objekt für den ActionListener (AktionsListener.java) und ein WindowListener (FensterListener.java).
Klassenintern hat uns der Lehrer bestimmen lassen wie wir lieber Fenster programmieren wollen, mit JFrame oder java.awt.Frame. Wir haben uns für Frame entschieden.
So wie ich den ActionListener in meiner Lösung hinzufüge, habe ich jetzt aus AktionsListener.java das "implements ActionListener" entfernt und habe nur noch die Methoden drin die bei einer Aktion ausgeführt werden.
Das ist so meine Vorgeschichte zu Java.
Ich freue mich über Kritik, wenn sie konstruktiv ist und setzte auch gerne neues um.
Mir geht es nicht um das Array, sondern um die von dir verwendete Reflection.
Reflection ist ein sehr mächtiges das für sehr wenige Spezialfälle reserviert ist.
Damit irgendwelche actionPerformed Methoden aufzurufen ist nicht nur totaller Overkill, sondern auch noch höchst unflexible und hässlich.
Um dir zu sagen wie man es besser machen könnte müsste man wissen was die Buttons tun.
Auch wäre der Code einiger dieser actionX Methoden hilfreich.
Du ungergräbst meine Autoritäää :bae:
Aber im ernst, ein via Reflection verknüpftes Tastenfeld(?) eines Taschenrechners kann nicht der Weisheit letzter Schluß sein :wink:
Ursprünglich wollte ich das ganze durch ein einfaches al.action/*irgendwie Variable i hier hin*/ lösen das ich zwischen die geschweiften Klammern von "new ActionListener()" klemme. Nur hab ich die Variable da nicht Variabel hin bekommen.
Was die Buttons machen steht eigentlich alles in der for-Schleife. bu[0] bis bu[9] sind die Buttons mit den Zahlen. Ich adde alle Buttons später nur noch auf die Oberfläche und benenne vorher noch die Buttons mit den Rechenoperatoren.
Code:
public void action0(ActionEvent e) {
if (Integer.parseInt(Fensta.disp.getText())==0);
else Fensta.disp.setText(Fensta.disp.getText()+0);
}
public void action1(ActionEvent e) {
Fensta.disp.setText(Fensta.disp.getText()+1);
}
public void action2(ActionEvent e) {
Fensta.disp.setText(Fensta.disp.getText()+2);
}
"disp" ist in Fensta die statische Variable für ein Label. Hier soll eigentlich nur beim Drücken eines Zahlenbuttons die Zahl auch angezeigt werden. Der Teil ist aber noch nicht ganz ausgereift, da ich noch mit dem Label etwas Kämpfe das seine Größe nicht automatisch anpasst wenn es aus einer anderen Methode als der in der ich es geaddet habe geändert wird. Für die nicht Zahlen Buttons habe ich deswegen noch keine auszuführenden Befehle eingetragen
P.S. Roar's Beitrag hab ich "überlesen", aber werde mir später anschauen was er meint :wink:
für alle Buttons{
buttons[i].setActionCommand(String.valueOf(i));
buttons[i].addActionListener(someActionListener);
// ^das ist immer der gleiche
}
someActionListener:
actionPerformed(ActionEvent e)
{
Fensta.disp.setText(Fensta.disp.getText()+e.getActionCommand());
}
Danke!!!
Coole Lösung funktioniert und vor allem viel kürzer und übersichtlicher, muss ich halt noch ausbauen dass es sich wirklich so verhält wie das bei einem normalen Rechner aussieht.
ABER :idea:: setActionCommand lass ich weg "By default this action command is set to match the label of the button." Heißt so viel wie i ist eh schon das action command :bae: .