JButton reagiert nicht auf actionListener

CConraths

Aktives Mitglied
Hallo Forum
ich habe mir eine kleine Anwendung zum Üben geschrieben.
Meine Klasse implementiert den ActionListener.
Mein Button bekommt den Actionlistener zugewiesen(addAction Listener(this).
Die Methode actionPerformed wird nach buttonclick aufgerufen this.btn.... ist aber null
????
Hilfe wäre erforderlich 😳
 
du übergibst im regelfall eine anonyme klasse ...die klasse ansich implementiert nicht den action listener
 
du übergibst im regelfall eine anonyme klasse ...die klasse ansich implementiert nicht den action listener
wie er schreibst wird er in der Klasse in der der Button ist das ActionListener Interface Implementiert haben und keine anonyme Klasse haben. (implements ActionListener).

@CConraths was meist du mit this.btn.... ist aber null?
zeige mal was du machen willst.
 
wie er schreibst wird er in der Klasse in der der Button ist das ActionListener interface implenentirt haben und keine anonyme Klasse haben. (implements ActionListener).
das meinte ich ja... dass das schonmal schmarn ist

er präsentiert problem X und hat eine Lösung Y und er versucht das problem bie Y zu lösen obwohl X das eigetnliche problem ist
 
Also erst einmal ist es vollkommen egal, ob die Klasse selbst ActionListener implementiert oder ob er es als Anonyme Klasse aufbaut: Beides ist komplett Out of Date und führt zu unleserlichem Code. Und es ist nur eine Nebelkerze des eigentlichen Problems:
this.btn.... ist aber null
Da ist die Frage lediglich, wie der Code genau aussieht. Es gibt mehrere triviale Probleme, die sowas hervor rufen würden:
- mehrere Instanzen einer Klasse werden erzeugt und man erwartet Werte einer Instanz in der Anderen.
- Bei der Initialisierung wir etwas in eine lokale Variable geschrieben, die die Instanzvariable verdeckt
- ...

Wenn der TE Code liefern sollte wäre es aber sehr toll, wenn ihm dann bezüglich Action Listener saubere Varianten gezeigt würden und nicht eine veraltete Praxis durch eine andere, ebenso veraltete Praxis ersetzt wird. (Just my 2 Cent)
 
Also erst einmal ist es vollkommen egal, ob die Klasse selbst ActionListener implementiert oder ob er es als Anonyme Klasse aufbaut: Beides ist komplett Out of Date und führt zu unleserlichem Code. Und es ist nur eine Nebelkerze des eigentlichen Problems:

Da ist die Frage lediglich, wie der Code genau aussieht. Es gibt mehrere triviale Probleme, die sowas hervor rufen würden:
- mehrere Instanzen einer Klasse werden erzeugt und man erwartet Werte einer Instanz in der Anderen.
- Bei der Initialisierung wir etwas in eine lokale Variable geschrieben, die die Instanzvariable verdeckt
- ...

Wenn der TE Code liefern sollte wäre es aber sehr toll, wenn ihm dann bezüglich Action Listener saubere Varianten gezeigt würden und nicht eine veraltete Praxis durch eine andere, ebenso veraltete Praxis ersetzt wird. (Just my 2 Cent)
Java:
package zaehlerstaende;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;

public class buttontest implements ActionListener{   
    private JFrame frame= new JFrame();
    JButton btnSpeichern = new JButton("Speichern");
    
    public static void main(String[] args) {
        buttontest bt = new buttontest();
        bt.fuellen();

    }

    private void fuellen() {
        
        JButton btnNewButton = new JButton("New button");
        btnNewButton.addActionListener(this);
        frame.getContentPane().add(btnNewButton, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);       
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == this.btnSpeichern) {     
            frame.pack();
        }
    }

}

zu frame.pack kommt er garnicht ist das == falsch ???
 
Du hast eine Instanzvariable btnSpeichern. Dieser weist Du einen neuen Button zu, den Du erstellst. Diesen fügst Du aber der Oberfläche nicht hinzu.

Die Methode fuellen erstellt einen neuen Button. Den fügst Du dem Panel hinzu. Diesen Button hast Du aber nur in einer lokalen Variable gespeichert.

Um Deinen Code zum laufen zu kriegen könntest Du den neu erstellten Button in der Instanzvariable speichern:
Java:
package zaehlerstaende;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;

public class buttontest implements ActionListener{   
    private JFrame frame= new JFrame();
    JButton btnSpeichern; // Hier keine Initialisierung mehr
    
    public static void main(String[] args) {
        buttontest bt = new buttontest();
        bt.fuellen();
    }

    private void fuellen() {
        btnSpeichern = new JButton("New button"); // Hier jetzt speichern des Buttons in Instanzvariable.
        btnSpeichern.addActionListener(this);
        frame.getContentPane().add(btnSpeichern, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);       
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // Hier ist jetzt btnSpeichern gefüllt ...
        if (e.getSource() == this.btnSpeichern) {     
            frame.pack();
        }
    }

}

Aber was ich schon etwas angesprochen habe: Dieser Aufbau ist veraltet. Dieser ganze Aufbao mit Abfrage, welcher Button denn das Event ausgelöst hat und so ist unnötig. Statt dessen kann man z.B. mittels sogenannter Methodenreferenz eine Methode vorgeben:

Du schreibst einfach eine Methode, was eben gemacht werden soll. Die Methode heisst auch so, dass der Name beschreibt, was denn da gerade gemacht wird. Also etwas wie:

Java:
public void endProgram(ActionEvent e) {
    System.exit();
}

Diese Methode kannst Du nun direkt zuweisen:
btnSpeichern.addActionListener(this::endProgram);

Damit dies funktioniert, muss die Methode von den Parametern passend sein. Aber das Beispiel zeigt ja, dass die Methode den Parameter ggf. gar nicht braucht:
Java:
public void endProgram() {
    System.exit();
}

Das kann dann nicht mehr mittels Methodenreferenz sondern statt dessen mit einem Lambda Ausdruck aufgerufen werden:
btnSpeichern.addActionListener(e -> endProgram());

Das wären so die üblichen Wege. Der Vorteil ist hierbei vor allem, dass du eine Methode schreibst, die genau das macht, was der Bezeichner der Methode auch aussagen sollte. Und es wird unnötiger Code vermieden.

Das einfach einmal in Kürze dazu. Methodenreferenz und Lambda Ausdrücke ansonsten einfach einmal nachlesen - dazu gibt es im Netz viele Einführungen.
 
btnSpeichern.addActionListener(this::endProgram);
das ist nur die kurze version von
btnspeichern.Add..(event->endProgram(event));
und das ist nur die kurz form voneiner anonymen klasse
Java:
btnSpeichern.Add..(new ActionListener(){
    handle...{
        
    }
})
unter veraltet versteht man "soll" man nicht hernehmen... du nimmst aber die anonyme klasse genauso her
 
Also erst einmal ist es vollkommen egal, ob die Klasse selbst ActionListener implementiert oder ob er es als Anonyme Klasse aufbaut: Beides ist komplett Out of Date und führt zu unleserlichem Code. Und es ist nur eine Nebelkerze des eigentlichen Problems:

Da ist die Frage lediglich, wie der Code genau aussieht. Es gibt mehrere triviale Probleme, die sowas hervor rufen würden:
- mehrere Instanzen einer Klasse werden erzeugt und man erwartet Werte einer Instanz in der Anderen.
- Bei der Initialisierung wir etwas in eine lokale Variable geschrieben, die die Instanzvariable verdeckt
- ...

Wenn der TE Code liefern sollte wäre es aber sehr toll, wenn ihm dann bezüglich Action Listener saubere Varianten gezeigt würden und nicht eine veraltete Praxis durch eine andere, ebenso veraltete Praxis ersetzt wird. (Just my 2 Cent)
 
das ist nur die kurze version von

und das ist nur die kurz form voneiner anonymen klasse
Java:
btnSpeichern.Add..(new ActionListener(){
    handle...{
       
    }
})
unter veraltet versteht man "soll" man nicht hernehmen... du nimmst aber die anonyme klasse genauso her
durch die aussage zweifel ich es nicht an dass die methoden referenz besser ist... aber wenn man nicht weis was dahinter steht dann versteht man auch nicht die referenz
 
hallo nochmal

habe die Version implementiert in der von actionLister des buttons direkt eine Methode mit sprechendem Namen gerufen wird
das mit -> e methodenname() habe ich noch nicht kapiert ist das die Lambda Version ???

macht Spaß aber ist zum Teil harte Kost für mich
danke an euch für die Erklärungen
 
was halt fancy ist an solchen lambdas, man kann sie nochmal kürzen
in dem man eine Methoden referenz übergibt
dh aus
e->methode(e)
wird
this::methode

weil das "e" ansich doppelt ist
 
@Joreyk Bitte mache Dich doch erst einmal schlau, ehe Du meinst jemanden angehen zu müssen.

Die Methodenreferen und die Lambda Expression haben nichts mit einer anonymen Klasse zu tun. Das sind absolut unterschiedliche Dinge! Es wird durch die neuen Konsrukte keine anonyme Klasse erzeugt! (Kannst Du z.B. an den nicht vorhandenen KlassenName$1.class und so erkennen!)

Und im Code hat man riesen Unterschiede - Zum einen die Möglichkeit, die Methode abweichend zu benennen und zum anderen die geringere Anzahl an Zeilen. Was ich doch auch geschrieben habe...

genau deswegen meinte ich dass man ohne grundkenntnisse nicht mit der referenz in die tür ffallen soll
f
Und er hat die Methodenreferenz richtig anwenden können. Damit hat es doch etwas gebracht, dass ich dies erwähnt habe. Er hat zwei Möglichkeiten aufgezeigt bekommen, eine davon direkt verstanden und die zweite kann er sich auch noch anlesen ==> Er lernt dazu! Das, wozu das Forum da ist!
 
Um das noch mal zu zeigen, folgender Code:
Java:
package playground;

import java.util.Arrays;

public class Play {

    public static void main(final String[] args) {
        Arrays.sort(new String[] {"A", "B"}, String::compareTo);
    }

}
Kompiliert zu: Play.class - keine anonyme Klasse im Package!

Aber folgender Code:
Java:
package playground;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Play {

    public static void main(final String[] args) {

        final MouseListener listener = new MouseListener() {
            @Override
            public void mouseReleased(final MouseEvent e) {}
            @Override
            public void mousePressed(final MouseEvent e) {}
            @Override
            public void mouseExited(final MouseEvent e) {}
            @Override
            public void mouseEntered(final MouseEvent e) {}
            @Override
            public void mouseClicked(final MouseEvent e) {}
        };

        System.out.println(listener);

    }

}
Kompiliert zu: Play.class und Play$1.class - hier wurde eine anonyme Klasse erstellt.
 

Zurück
Oben