J'essaie de comprendre ce que je fais de 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'actions.
Vous trouverez ci-dessous un programme simple qui tente de faire fonctionner un bouton.
Qu'est-ce que je fais 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)
}
}
le programme d'écoute d'action n'est jamais enregistré car, avec la fonction if(e.getSource() == button1)
, il ne peut pas voir le code button1
, les erreurs indiquant le symbole introuvable
Il n'y a pas de pointeur this
dans une méthode statique. (Je ne crois pas que ce code sera même compilé.)
Vous ne devriez pas faire ces choses avec une méthode statique comme main()
; mettre les choses en place dans un constructeur. Je n'ai pas compilé ou exécuté ceci pour voir si cela fonctionne réellement, mais essayez.
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)
}
}
Je suis étonné que personne n'ait mentionné l'utilisation d'une commande d'action. C'est un moyen assez classique d'associer des sources et des auditeurs. C'est vraiment utile si;
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");
}
}
}
Voici une forme modifiée de la source basée sur mon commentaire. Notez que les interfaces graphiques doivent ê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);
}
}
On vous a dit comment régler 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 jetable. Cela signifie des cas initiaux pour les noms de classe.
Ne prolongez pas les cours dont vous n'avez pas besoin. JFrame
devrait rarement être prolongé. En fait, vous ne créez pas d'instance de votre classe dérivée !!!
Ne regroupez pas un tas de choses dans une classe. En particulier, vous ne devez généralement sous-taper qu’au plus une classe ou interface principale à la fois (des éléments tels que Comparable
non inclus).
Interagissez toujours, y compris la construction, les interfaces graphiques Swing/AWT sur le thread EDT (AWT Event Dispatch Thread). C'est moche et prolixe, mais c'est Java pour vous.
Vérifier la source d'un événement est un peu de piratage. Les auditeurs sont de petite taille, vous ne pouvez donc même pas prétendre que l'excuse de performance boiteuse
Alors:
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 devez accéder à l'une des variables à partir de la méthode englobante dans l'écouteur, rendez-les final
.
Le problème est que button1 est une variable locale. Vous pouvez le faire en modifiant 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.
Le premier problème est que button1
est une variable locale de la méthode main
; la méthode actionPerformed
n'y a donc pas accès.
Le deuxième problème est que l'interface ActionListener
est implémentée par la classe calc
, mais aucune instance de cette classe n'est créée dans la méthode main
.
La manière habituelle de faire ce que vous voulez est de créer une instance de calc
et de transformer button1
en champ de la classe calc
.
Vous déclarez button1 dans la méthode main 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)
}
J'utilise "e.getActionCommand (). Contient (CharSecuence s)", car je viens d'un contexte MVC et le bouton est déclaré dans la classe View, mais l'appel à actionPerformed a lieu 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ôleurs implémente ActionListener, et donc, lors de la substitution de 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 autre réponse est également utile.
Tout d’abord, étendez correctement JFrame avec un super () et un constructeur, puis ajoutez des écouteurs d’action 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);
}
}