Comment ajouter un écouteur d'action qui écoute plusieurs boutons

J'essaie de comprendre ce que je fais mal avec les auditeurs d'action. Je suis plusieurs tutoriels et pourtant netbeans et eclipse me donnent des erreurs lorsque je tente d'utiliser un écouteur d'action.

Ci-dessous est un programme simple que je tente d'obtenir un bouton de travail.

Qu'est-ce que je fais de mal?

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

}

L'écouteur d'action n'est jamais enregistré car avec le if(e.getSource() == button1) Il ne peut pas voir button1, les erreurs disant ne peuvent pas trouver le symbole.

26
demandé sur skaffman 2011-05-09 15:31:33

9 réponses

Il n'y a pas de pointeur this dans une méthode statique. (Je ne crois pas que ce code va même compiler.)

Vous ne devriez pas faire ces choses dans une méthode statique comme main(); Configurez les choses dans un constructeur. Je n'ai pas compilé ou exécuté ceci pour voir si cela fonctionne réellement,mais essayez-le.

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
répondu duffymo 2013-04-17 19:55:16

Je suis étonné que personne n'ait mentionné l'utilisation d'une commande d'action. C'est une façon assez standard d'associer des sources et des auditeurs. C'est vraiment utile si;

  • Vous avez plusieurs sources d'événements qui doivent faire la même chose (par exemple, si vous voulez que l'use puisse appuyer sur la touche Entrée sur un champ de texte comme alternative à cliquer sur un bouton à côté)
  • vous n'avez pas de référence au composant générant l'événement

Voir;

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
répondu Qwerky 2011-05-09 13:32:42

Voici une forme modifiée de la source basée sur mon commentaire. Notez que les interfaces graphiques devraient être construites et mises à jour sur L'EDT, bien que je ne sois pas allé aussi loin.

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
répondu Andrew Thompson 2016-04-24 10:50:27

Le problème est que button1 est une variable locale. Vous pouvez le faire en changeant simplement la façon dont vous ajoutez l'actionListener.

button.addActionListener(new ActionListener() {  
            public void actionPerformed(ActionEvent e)
            {
                //button is pressed
                System.out.println("You clicked the button");
            }});

Ou vous faites button1 une variable globale.

2
répondu cb0 2011-05-09 11:42:13

On vous a dit comment trier votre problème immédiat, mais je pense qu'il y a des problèmes plus importants ici.

  • S'en tenir aux conventions. Même pour le code à jeter. Cela signifie des cas initiaux pour les noms de classe.

  • N'étendez pas les classes dont vous n'avez pas besoin. JFrame devrait rarement être étendu. En fait, vous ne créez pas une instance de votre classe dérivée!!!

  • Ne pas regrouper un tas de choses dans une classe. En particulier, vous devriez généralement seulement sous-type au plus une classe principale ou une interface à la fois (des choses comme Comparable non inclus).

  • Interagissez toujours, y compris les interfaces graphiques construct, Swing/AWT sur le Thread de répartition des événements AWT (EDT). C'est moche et verbeux, mais C'est Java pour vous.

  • Vérifier une source d'un événement est un peu de hack. Les auditeurs sont petits, donc vous ne pouvez même pas prétendre à l'excuse de performance boiteuse.

Donc:

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

Si vous avez besoin d'accéder à l'une des variables enfermant la méthode dans l'écouteur, faites-les final.

2
répondu Tom Hawtin - tackline 2011-05-09 12:30:45

Le premier problème est que button1 est une variable locale de la méthode main, donc la méthode actionPerformed n'y a pas accès.

Le deuxième problème est que la ActionListener interface est implémentée par la classe calc, mais aucune instance de cette classe est créée dans le main méthode.

La façon habituelle de faire ce que vous voulez est de créer une instance de calc et faire button1 un champ de la calc classe.

1
répondu Laurent Pireyn 2011-05-09 11:36:41

Vous déclarez button1 dans la méthode principale afin que vous ne puissiez pas y accéder dans actionPerform. Vous devriez le rendre global en classe.

 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
répondu Harry Joy 2011-05-09 11:34:27

Tout d'abord, exend JFrame correctement avec un super () et un constructeur ajoutez ensuite actionlisteners au cadre et ajoutez les boutons.

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
répondu Jon Takagi 2013-02-25 01:07:43

J'utilise " E. getActionCommand ().contains(CharSecuence s)", puisque Im provenant d'un contexte MVC, et le bouton est déclaré dans la classe View, mais l'appel actionPerformed se produit dans le contrôleur.

public View() {
    ....
    buttonPlus = new Button("+");
    buttonMinus = new Button("-");
    ....
}

public void addController(ActionListener controller) {
    buttonPlus.addActionListener(controller);
    buttonMinus.addActionListener(controller);
}

MA classe de contrôleur implémente ActionListener, et donc, en remplaçant actionPerformed:

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

J'espère que cette réponse est également utile.

0
répondu Omar N 2017-02-12 18:33:20