2009-03-21 8 views
1

Je suis nouveau dans le développement d'applications Windows en utilisant Java. La question est la suivante: "Comment lier des événements à des méthodes de classes personnalisées?Java Event Binding

Comme je l'ai vu, je peux enregistrer des classes d'écouteurs pour balancer des composants afin de gérer des événements, mais je dois implémenter une classe qui implémente par ex. ActionListener interface pour gérer un événement, puis implémenter la méthode actionPerformed.C'est à dire une classe pour chaque événement que je dois gérer

Impossible d'avoir une classe "écoute" pour les événements de tous les composants et avoir chaque méthode dans ce classe est-ce que la gestion des événements est effectuée? "

Un exemple:

class MyEventListener { //pseudo code [no constructors, etc] 

    public void handleSubmitFormBtn(Event e) { 

    } 

    //other methods go here handling events from other swing components 
} 

Note: Je ne suis pas sûr de la signature de la méthode, mais je souhaite que vous obtenez le point. Conclusion: Une méthode pour gérer les événements déclenchés par des composants pivotants. Est-ce possible? Est-ce que la création d'une classe pour chaque événement est le seul moyen? Impossible de router la gestion des événements vers des méthodes spécifiques pour une seule classe?

Répondre

2

Vous avez quelques choix, chacun avec leurs avantages/inconvénients particuliers.

classes internes anonymes

component.addActionListener(
    new ActionListener() 
    { 
     public void actionPerformed(final ActionEvent e) 
     { 
      outerClassesMethod(); 
     } 
    }); 

classe intérieure

class Foo 
    implements ActionListener 
{ 
    public void actionPerformed(final ActionEvent e) 
    { 
     outerClassMethod(); 
    } 
} 

de la classe externe

public class Foo 
    implements ActionListener 
{ 
    private final OuterClass target; 

    public Foo(final OuterClass t) 
    { 
     target = t; 
    } 

    public void actionPerformed(final ActionEvent e) 
    { 
     target.targetClassMethod(); 
    } 
} 

classe implémente auditeur

public class OuterClass 
    implements ActionListener 
{ 
    public void actionPerformed(final ActionEvent e) 
    { 
     method(); 
    } 

    // somewhere else in the code 
    { 
     component.addActionListener(this); 
    } 
} 

Chaque chemin a une bonne et mauvaise à elle.

La classe interne anonyme ne vous permet pas de faire ce que vous demandez, elle ne peut implémenter qu'un seul écouteur.

Les trois autres vous permettront de faire ce que vous voulez (il suffit d'ajouter WindowListener à la liste des outils pour exaple). Vous voulez probablement que la classe interne ou la classe externe implémente le mode d'écoute pour faire ce que vous voulez. Je suggère que parce que l'auditeur est très fortement couplé à votre programme, et vous aurez besoin de faire un grand nombre d'instructions "if" pour déterminer quel contrôle a été utilisé pour effectuer l'action réelle (vous utilisez evt.getSource() pour déterminer quel contrôle était en action et ensuite le communiquer à vos variables d'instance pour voir de quoi il s'agissait). Toutefois, à moins que vous ne soyez en mémoire, comme un téléphone Android, vous ne devriez probablement pas utiliser une seule méthode pour tous les écouteurs car cela peut facilement conduire à un très mauvais code. Si la mémoire est un problème, alors allez-y, mais si ce ne vous êtes mieux de faire l'une des choses suivantes:

  • une classe d'écoute par commande
  • une classe d'écoute par type d'événement pour tous contrôle
  • une classe d'écoute par le contrôle par type d'événement

Je préfère coder de la façon suivante, je trouve être le plus flexible:

public class Outer 
    extends JFrame 
{ 
    private final JButton buttonA; 
    private final JButton buttonB; 

    { 
     buttonA = new JButton("A"); 
     buttonB = new JButton("B"); 
    } 

    // do not put these in the constructor unless the Outer class is final 
    public void init() 
    { 
     buttonA.addActionListener(new AListener()); 
     buttonB.addActionListener(new BListener()); 
    } 

    private void aMethod() 
    { 
    } 

    private void bMethod() 
    { 
    } 

    public void AListener 
     implements ActionListener 
    { 
     public void actionPerformed(final ActionEvent evt) 
     { 
      aMethod(); 
     } 
    } 

    public void BListener 
     implements ActionListener 
    { 
     public void actionPerformed(final ActionEvent evt) 
     { 
      bMethod(); 
     } 
    } 
} 

Je préfère de cette façon parce qu'elle force les méthodes hors des écouteurs, ce qui signifie que je n'ai qu'un seul endroit pour chercher le code (pas dispersé dans les classes internes). Cela signifie également qu'il est possible que aMethod() et bMethod() puissent être réutilisés - si le code est dans un programme d'écoute qui n'est pas pratique (c'est possible, mais cela n'en vaut pas la peine). Le faire de la manière ci-dessus est également cohérent, et je préfère la cohérence sur la plupart des choses, sauf s'il y a une bonne raison de ne pas le faire. Par exemple sur Android je ne le fais pas car la création de classe est chère (j'ai toujours les méthodes d'appel de l'écouteur seulement, mais la classe elle-même implémente les écouteurs et je fais une instruction if).

1

Vous pouvez le faire en créant un seul écouteur d'action qui bascule alors sur la source d'entrée, donc quelque chose comme:

public void actionPerformed(ActionEvent e) { 
    if (e.getSource() == buttonA) { 
     doSomethingForButtonA(e); 
    } else if (e.getSource() == buttonB) { 
     doSomethingForButtonB(e); 
    } 
} 

Mais ce n'est pas la méthode recommandée pour le faire pour diverses raisons. Pourquoi avez-vous un problème avec la création d'un écouteur pour chaque événement à recevoir? C'est le modèle Java pour la gestion des événements de l'interface utilisateur, et si quelqu'un d'autre utilise votre code ou si vous utilisez un code de quelqu'un d'autre, cela sera attendu.

4

bat ce que vous faites habituellement est d'utiliser une classe anonyme pour gérer vos événements, comme ceci:

someControl.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      // handle the event 
     } 
    }); 

Bien que vous pouvez en principe avoir une manipulation classe tous vos événements et inscrivez-vous à tous les gestionnaires, anonyme Les classes, comme mentionné ci-dessus, sont l'idiome swing correct pour gérer les événements.

Vous trouverez beaucoup plus d'info @http://java.sun.com/docs/books/tutorial/uiswing/events/generalrules.html

+0

À moins que votre action ne délègue à un contrôleur et n'a donc qu'un seul appel de méthode dans la classe anonyme, je ressemble vraiment à cette approche car elle ne fait qu'encombrer le code. Je préfère tout ce qui fait du travail dans une classe séparée – tddmonkey

0

Vous pouvez avoir une classe qui a des méthodes d'écoute de nombreux événements:

0

Une solution conceptuelle consisterait à implémenter le MOTIF OBSERVER.

0

Le cadre Melasse permet de coller le composant UI avec le modèle sans création de classe (même anonyme), avec la syntaxe Binder.bind(/* source, target, options */).Par exemple, une nouvelle classe n'est pas nécessaire pour activer une action/bouton uniquement lorsqu'un texte est présent dans un champ de texte: https://github.com/cchantep/melasse/blob/master/README.md#bind-buttonaction-to-provided-value. Idem pour afficher/masquer des informations ou des erreurs.

La plupart des composants de l'interface utilisateur sont pris en charge, tous les beans Java (avec prise en charge de la modification des propriétés) le sont.