2009-08-28 6 views
5

Fondamentalement, ce que je veux faire est d'obtenir un bouton de démarrage pour lancer une méthode s'exécutant dans une autre classe et agissant sur un autre objet.Java: Utiliser un actionlistener pour appeler une fonction dans une autre classe sur un objet de cette classe

Mon code pour l'auditeur:

button1a.addActionListener(new ActionListener() { 
    public void actionPerformed (ActionEvent event) { 
     // Figure out how to make this work 
     //sim.runCastleCrash(); 
    } 
}); 

Mon code pour l'autre classe:

public static void main(String[] args) { 
    CastleCrash sim; 
    sim = new CastleCrash(); 
} 

et

public void runCastleCrash() { 
    System.out.println("Castle Crash is beginning..."); 
    //Other method parts here to be added 
} 

Je sens cela ne peut pas être trop dur , mais il me manque un morceau.

+0

Quelles sont les erreurs? La variable 'sim' est-elle dans la portée même lorsque vous essayez d'ajouter l'actionListener au bouton? Un écueil typique est que les variables doivent être finales pour être accessibles à partir d'une classe interne anonyme telle que votre ActionListener. –

+0

Je reçois l'erreur: Exception dans le thread « principal » java.lang.Error: problème de compilation non résolues: \t sim ne peut pas être résolu Je pense que vous avez raison en ce que son problème avec sim de ne pas être dans le champ d'application, mais je ne peux pas comprendre comment le rendre final .... – Myles

+0

Voir la réponse par McDowell, c'est ce que je répondrais. –

Répondre

3

Une façon de référencer les choses dans une classe anonyme utilise le final mot-clé:

public static void main(String[] args) { 
    final Object thingIWantToUse = "Hello"; 

    JButton button = new JButton("Click"); 
    button.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent e) { 
     System.out.println(thingIWantToUse); 
     } 
    }); 

    JFrame frame = new JFrame(); 
    frame.setLayout(new FlowLayout()); 
    frame.add(button); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setVisible(true); 
    } 

Vous pouvez également accéder aux membres (variables ou méthodes) d'un type englobante:

public class ActionListenerDemo2 { 
    private final JFrame frame = new JFrame(); 
    private Object thingIWantToUse = "Hello"; 

    public ActionListenerDemo2() { 
    JButton button = new JButton("Click"); 
    button.addActionListener(new ActionListener() { 
     @Override public void actionPerformed(ActionEvent e) { 
     thingIWantToUse = "Goodbye"; 
     System.out.println(thingIWantToUse); 
     } 
    }); 
    frame.setLayout(new FlowLayout()); 
    frame.add(button); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
    new ActionListenerDemo2().frame.setVisible(true); 
    } 
} 
+0

Je ne comprends pas très bien la deuxième option que vous décrivez. Comment est-il possible d'accéder aux méthodes d'un type englobant? – Myles

+0

Si vous avez ajouté une méthode 'doFoo()' à AnctionListenerDemo2', vous pouvez l'appeler depuis 'actionPerformed'. 'actionPerformed' appartient à l'implémentation de classe interne anonyme de l'interface' ActionListener'. Intro aux classes imbriquées ici: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html – McDowell

0

D'une manière ou d'une autre, vous avez besoin d'une référence à votre objet CastleCrash disponible pour appeler depuis votre actionListener.

Vous voudrez probablement sous-classer JFrame, ou tout ce qui contient votre JButton de sorte qu'il possède à la fois votre méthode principale et une propriété CastleCrash qui peuvent ensuite être référencées à partir de votre classe interne anonyme Actionlistener. MAIS - faites attention, vous avez l'air d'appeler une méthode longue durée à partir du thread d'événement GUI (où l'écouteur d'action sera appelé). C'est généralement une mauvaise idée, vous allez faire en sorte que votre interface graphique ne réponde plus.

Voir http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html en particulier le bit sur la classe SwingWorker pour des idées sur la façon d'éviter ce problème.

1

McDowell répond déjà pratiquement avec de bons exemples sur la façon d'accéder aux variables des auditeurs d'événements (ou des classes internes anonymes en général). Il y a cependant a more general Sun resource on Event Listeners in Swing qui est canonique et un bon aperçu de toutes les mises en garde à prendre en compte lors de leur écriture.

2

J'ai eu le même problème que vous et voici comment je l'ai résolu. Vous pouvez soit rendre votre objet final (final CastleCrash sim = new CastleCrash();), mais je ne voulais pas faire cela, ou vous pouvez faire quelque chose comme une méthode setter pour exécuter la méthode dans votre autre classe :

Mon code pour la classe auditeur:

button1a.addActionListener(new ActionListener() 
{ 

    public void actionPerformed (ActionEvent event) 
    { 
    //How to make this work ? 
    //Like this: 
    runCC(); 
    } 
}); 

public void runCC() 
{ 
    CastleCrash sim = new CastleCrash(); 
    sim.runCastleCrash(); 
} 

Mon code pour l'autre classe:

public void runCastleCrash() 
{ 
    System.out.println("Castle Crash is beginning..."); 
    //Other method parts here to be added 
} 

Espérons que cela est utile, bonne chance! :)

Questions connexes