2009-08-28 7 views
5

Fondamentalmente quello che voglio fare è ottenere un pulsante di avvio per avviare un metodo in esecuzione in un'altra classe e agire su un altro oggetto.Java: utilizzo di un listener di azioni per chiamare una funzione in un'altra classe su un oggetto di quella classe

Il mio codice per l'ascoltatore:

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

Il mio codice per l'altra classe:

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

e

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

ho la sensazione questo non può essere troppo difficile , ma mi manca un pezzo.

+0

Quali errori stai ottenendo? La variabile 'sim' è valida anche quando cerchi di aggiungere actionListener al pulsante? Una tipica trappola è che le variabili devono essere definitive per essere accessibili da una classe interna anonima come ActionListener. –

+0

ottengo l'errore: Exception in thread "main" java.lang.Error: non risolto problema di compilazione: \t sim non può essere risolto Penso che tu abbia ragione in quanto il suo un problema con sim non essendo nel campo di applicazione, ma non riesco a capire come renderlo definitivo .... – Myles

+0

Vedere la risposta di McDowell, ecco cosa risponderei. –

risposta

3

Un modo per fare riferimento a cose in una classe anonima sta usando la parola chiave final:

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

In alternativa, è possibile accedere ai membri (variabili o metodi) di un tipo di inclusione:

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

Non capisco bene la seconda opzione che descrivi. Com'è possibile accedere ai metodi di un tipo che racchiude? – Myles

+0

Se hai aggiunto un metodo 'doFoo()' a 'AnctionListenerDemo2', puoi chiamarlo da dentro 'actionPerformed'. 'actionPerformed' appartiene all'implementazione anonima della classe interna dell'interfaccia' ActionListener'. Introduzione alle classi nidificate qui: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html – McDowell

0

In qualche modo è necessario un riferimento all'oggetto CastleCrash disponibile per chiamare dal proprio actionListener.

Probabilmente vuoi creare una sottoclasse di JFrame, o qualsiasi altra cosa contenga il tuo JButton in modo tale che abbia sia il tuo metodo principale che una proprietà di CastleCrash che può quindi essere referenziata dal tuo Actionlistener della classe interna anonima.

MA, fai attenzione, sembra che tu stia chiamando quale sarà un metodo a lunga esecuzione all'interno del thread di eventi della GUI (dove verrà chiamato il listener di azioni). Questa è generalmente una cattiva idea, la tua GUI non risponderà.

Vedere http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html in particolare il bit sulla classe SwingWorker per idee su come evitare tale problema.

1

McDowell già risponde praticamente con buoni esempi su come accedere alle variabili dagli ascoltatori di eventi (o classi interne anonime in generale). C'è comunque a more general Sun resource on Event Listeners in Swing che è canonico e una buona panoramica di tutti gli avvertimenti da tenere in considerazione durante la scrittura.

2

Ho avuto lo stesso problema come te e questo è il modo in cui l'ho risolto.

Puoi rendere l'oggetto finale (CastleCrash finale sim = new CastleCrash();), ma non volevo farlo, oppure puoi fare qualcosa come un metodo setter per eseguire il metodo nell'altra classe :

il mio codice per la classe ascoltatore:

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

il mio codice per l'altra classe:

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

Spero che questo è utile, buona fortuna! :)