it-swarm.com.de

So fügen Sie einen Aktionslistener hinzu, der auf mehrere Schaltflächen wartet

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. 

26
user519670

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)
    }  

}
35
duffymo

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;

  • sie haben mehrere Ereignisquellen, die dasselbe tun müssen (z. B. wenn Sie möchten, dass der Benutzer die Eingabetaste in einem Textfeld als Alternative zum Klicken auf eine Schaltfläche daneben drücken kann.)
  • sie haben keinen Verweis auf die Komponente, die das Ereignis generiert 

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");
    }
  }
}
19
Qwerky

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);
    }
}
9
Andrew Thompson

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.

2
cb0

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.

1
Laurent Pireyn

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 .

0
Johnny

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)
}
0
Harry Joy

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.

0
Omar N

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);
    }
}
0
Jon Takagi