Ich versuche herauszufinden, was ich mit Action-Hörern falsch mache. Ich verfolge mehrere Tutorials und trotzdem geben mir Netbeans und Eclipse Fehler, wenn ich versuche, einen Aktionslistener zu verwenden.
Nachfolgend finden Sie ein einfaches Programm, das versucht, einen Button zum Laufen zu bringen.
Was mache ich falsch?
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class calc extends JFrame implements ActionListener {
public static void main(String[] args) {
JFrame calcFrame = new JFrame();
calcFrame.setSize(100, 100);
calcFrame.setVisible(true);
JButton button1 = new JButton("1");
button1.addActionListener(this);
calcFrame.add(button1);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1)
}
}
der Aktionslistener ist niemals registriert, da er mit if(e.getSource() == button1)
nicht button1
angezeigt werden kann.
In einer statischen Methode gibt es keinen this
-Zeiger. (Ich glaube nicht, dass dieser Code überhaupt kompiliert wird.)
Sie sollten diese Dinge nicht in einer statischen Methode wie main()
ausführen. Dinge in einem Konstruktor einrichten. Ich habe das nicht kompiliert oder ausgeführt, um zu sehen, ob es tatsächlich funktioniert, aber probieren Sie es aus.
public class Calc extends JFrame implements ActionListener {
private Button button1;
public Calc()
{
super();
this.setSize(100, 100);
this.setVisible(true);
this.button1 = new JButton("1");
this.button1.addActionListener(this);
this.add(button1);
}
public static void main(String[] args) {
Calc calc = new Calc();
calc.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1)
}
}
Ich bin erstaunt, dass niemand mit einem Aktionsbefehl erwähnt hat. Dies ist eine ziemlich übliche Art, Quellen und Hörer zu verknüpfen. Es ist wirklich nützlich, wenn;
sehen;
import Java.awt.FlowLayout;
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class DontExtendJFrame implements ActionListener {
private enum Actions {
HELLO,
GOODBYE
}
public static void main(String[] args) {
DontExtendJFrame instance = new DontExtendJFrame();
JFrame frame = new JFrame("Test");
frame.setLayout(new FlowLayout());
frame.setSize(200, 100);
JButton hello = new JButton("Hello");
hello.setActionCommand(Actions.HELLO.name());
hello.addActionListener(instance);
frame.add(hello);
JButton goodbye = new JButton("Goodbye");
goodbye.setActionCommand(Actions.GOODBYE.name());
goodbye.addActionListener(instance);
frame.add(goodbye);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand() == Actions.HELLO.name()) {
JOptionPane.showMessageDialog(null, "Hello");
} else if (evt.getActionCommand() == Actions.GOODBYE.name()) {
JOptionPane.showMessageDialog(null, "Goodbye");
}
}
}
Hier ist eine modifizierte Form der Quelle basierend auf meinem Kommentar. Beachten Sie, dass GUIs auf dem EDT erstellt und aktualisiert werden sollten, obwohl ich nicht so weit gegangen bin.
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JFrame;
public class Calc {
public static void main(String[] args) {
JFrame calcFrame = new JFrame();
// usually a good idea.
calcFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JButton button1 = new JButton("1");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JOptionPane.showMessageDialog(
button1, "..is the loneliest number");
}
});
calcFrame.add(button1);
// don't do this..
// calcFrame.setSize(100, 100);
// important!
calcFrame.pack();
calcFrame.setVisible(true);
}
}
Ihnen wurde gesagt, wie Sie Ihr unmittelbares Problem sortieren sollen, aber ich denke, es gibt hier wichtigere Probleme.
bei den Konventionen bleiben. Sogar für Wegwerfcode. Dies bedeutet erste Fälle für Klassennamen.
Erweitern Sie keine Klassen, die Sie nicht benötigen. JFrame
sollte selten erweitert werden. Tatsächlich erstellen Sie keine Instanz Ihrer abgeleiteten Klasse !!!
Bündeln Sie nicht mehrere Dinge in eine Klasse. Insbesondere sollten Sie im Allgemeinen immer nur eine Hauptklasse oder ein Interface gleichzeitig verwenden (z. B. Comparable
nicht enthalten).
Interagieren Sie immer, einschließlich Konstrukten, Swing/AWT-GUIs im AWT Event Dispatch Thread (EDT). Es ist hässlich und wortreich, aber das ist Java für Sie.
Das Überprüfen der Quelle eines Ereignisses ist ein bisschen Hack. Die Zuhörer sind klein, so dass Sie nicht einmal die schlechte Performance-Entschuldigung behaupten können.
So:
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Calc {
public static void main(String[] args) {
Java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
runEDT();
}});
}
private static void runEDT() {
assert Java.awt.EventQueue.isDispatchThread();
JFrame frame = new JFrame();
frame.setSize(100, 100);
JButton button1 = new JButton("1");
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
...
}
});
frame.add(button1);
frame.setVisible(true);
}
}
Wenn Sie auf eine der Variablen von der umgebenden Methode im Listener aus zugreifen müssen, machen Sie sie zu final
.
Das Problem ist, dass button1 eine lokale Variable ist. Sie können dies tun, indem Sie einfach die Art und Weise ändern, wie Sie den actionListener hinzufügen.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//button is pressed
System.out.println("You clicked the button");
}});
Oder Sie machen button1
zu einer globalen Variablen.
Das erste Problem ist, dass button1
eine lokale Variable der main
-Methode ist, sodass die actionPerformed
-Methode keinen Zugriff darauf hat.
Das zweite Problem ist, dass die ActionListener
-Schnittstelle von der Klasse calc
implementiert wird, dass jedoch keine Instanz dieser Klasse in der main
-Methode erstellt wird.
Normalerweise erstellen Sie eine Instanz von calc
und machen button1
zu einem Feld der calc
-Klasse.
Hier gibt es gute Antworten, aber lassen Sie mich den allgemeineren Punkt des Hinzufügens eines Aktionslisteners ansprechen, der mehrere Tasten abhört.
Es gibt zwei gängige Ansätze.
Verwenden eines allgemeinen Aktionslisteners
Sie können die Quelle der Aktion in Ihrer actionPerformed(ActionEvent e)
-Implementierung abrufen:
JButton button1, button2; //your button
@Override
public void actionPerformed(ActionEvent e) {
JButton actionSource = (JButton) e.getSource();
if(actionSource.equals(button1)){
// YOU BUTTON 1 CODE HERE
} else if (actionSource.equals(button2)) {
// YOU BUTTON 2 CODE HERE
}
}
ActionCommand verwenden
Mit dieser Methode legen Sie das Feld actionCommand
Ihrer Schaltfläche fest, mit dem Sie später switch
verwenden können:
button1.setActionCommand("actionName1");
button2.setActionCommand("actionName2");
Und später:
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand = ((JButton) e.getSource()).getActionCommand();
switch (actionCommand) {
case "actionName1":
// YOU BUTTON 1 CODE HERE
break;
case "actionName2":
// YOU BUTTON 2 CODE HERE
break;
}
}
Check out to Weitere Informationen zu JFrame-Schaltflächen, Listenern und Feldern .
Sie deklarieren button1 in der main-Methode, sodass Sie nicht in actionPerform darauf zugreifen können. Sie sollten es in der Klasse global machen.
JButton button1;
public static void main(String[] args) {
JFrame calcFrame = new JFrame();
calcFrame.setSize(100, 100);
calcFrame.setVisible(true);
button1 = new JButton("1");
button1.addActionListener(this);
calcFrame.add(button1);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1)
}
Ich verwende "e.getActionCommand (). Contains (CharSecuence s)", da ich aus einem MVC-Kontext komme und der Button in der View-Klasse deklariert ist, der actionPerformed-Aufruf jedoch im Controller ausgeführt wird.
public View() {
....
buttonPlus = new Button("+");
buttonMinus = new Button("-");
....
}
public void addController(ActionListener controller) {
buttonPlus.addActionListener(controller);
buttonMinus.addActionListener(controller);
}
Meine Controller-Klasse implementiert ActionListener. Wenn Sie actionPerformed überschreiben:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().contains("+")) {
//do some action on the model
} else if (e.getActionCommand().contains("-")) {
//do some other action on the model
}
}
Ich hoffe, diese andere Antwort ist auch nützlich.
Erweitern Sie zunächst JFrame richtig mit einem super () - und einem Konstruktor Fügen Sie dann Aktions-Listener zum Frame hinzu und fügen Sie die Schaltflächen hinzu.
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Calc extends JFrame implements ActionListener {
JButton button1 = new JButton("1");
JButton button2 = new JButton("2");
public Calc()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(100, 100);
button1.addActionListener(this);
button2.addActionListener(this);
calcFrame.add(button1);
calcFrame.add(button2);
}
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if(source == button1)
{
\\button1 code here
} else if(source == button2)
{
\\button2 code here
}
}
public static void main(String[] args)
{
JFrame calcFrame = new JFrame();
calcFrame.setVisible(true);
}
}