2013-07-31 10 views
5

Per esporre un po 'di più, ho una GUI che assomiglia:GUI non aggiornare visivamente prima di eseguire ActionEvent

enter image description here

Poi ho un listener di azione sul pulsante OK che inizia come:

//OK Button Action Listener 
private void okButtonActionPerformed(ActionEvent e) { 
    //Enable/Disable Buttons 
    okButton.setEnabled(false); 
    cancelButton.setEnabled(true); 
    updateCheckbox.setEnabled(false); 
    //Move on to a series of other methods here... 

che dovrebbe, in teoria, rendere questo accada:

enter image description here

Tuttavia, invece, ricevo il seguente fino a quando tutti i metodi e le altre cose connesse al pulsante OK sono stati completati:

enter image description here

Questo ovviamente non può accadere, perché l'idea è quella di rendere il pulsante di annullamento disponibile e il pulsante OK e diverse altre caselle di spunta non disponibili per la durata del programma (Immagine 2), dove, invece, si blocca in un semistato (Immagine 3). C'è un modo per combattere questo?

+0

tutto dentro ActionListener è fatto (sullo schermo) in un momento, dopo vengono eseguite tutte le linee di codice, si prega di che cosa è vero obiettivo – mKorbel

+0

Sto avendo difficoltà a capire esattamente quello che vuoi dire, ma essenzialmente ho un lungo processo in esecuzione che deve accadere pur mantenendo la GUI disponibile. Sulla base di altre risposte, dovrei usare un'altra discussione tramite 'SwingWorker'. – JTApps

+0

Ho un processo di lunga durata ---> quindi segue e accetta una delle risposte qui, molti esempi di codice, alcuni con descrizioni eccellenti – mKorbel

risposta

6

Ogni volta che si esegue la logica dalla GUI si dovrebbe utilizzare lo SwingWorker nel seguente modo:

SwingWorker myWorker= new SwingWorker<String, Void>() { 
    @Override 
    protected String doInBackground() throws Exception { 
     //Execute your logic 
     return null; 
    } 
}; 
myWorker.execute(); 

Se si desidera aggiornare la GUI da dentro questo uso logica invokeLater:

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     //To update your GUI 
    } 
}); 

Con questo si può essere sicuri che la tua logica e la tua interfaccia grafica restino reattive.

Edit:

Si potrebbe anche usare invokeAndWait se questo si adatta alle vostre esigenze di più. Link to related answer

+0

Ehm, non così tanto. All'interno di 'SwingWorker' c'è un ottimo framework per il passaggio degli aggiornamenti intermedi usando' publish' e 'process'; perché mai useresti 'invokeLater' ?! –

+0

La logica che seguo è qui: http://stackoverflow.com/a/7196920/1611957 Potresti spiegare perché pensi che non si applica? Voglio dire ... lo rende facile. – bjedrzejewski

+0

Poiché 'SwingWorker' ha già una coda di task asincrona per cui è possibile passare gli elementi in' process' e quindi EDT chiamerà 'publish'. Esegui l'override di 'publish' e utilizzi l'elemento per aggiornare la GUI. Il tuo metodo richiede la creazione di un'altra classe anonima (vale a dire il 'Runnable') e se vuoi passare qualsiasi dato al suo interno allora deve essere 'final' ecc. Inoltre devi considerare la sicurezza dei thread come il' Runnable' sarà invocato dall'EDT. –

3

// passare ad una serie di altri metodi qui ...

Assicurarsi di non bloccare il thread GUI (EDT) con operazioni di lunga durata. Utilizzare invece SwingWorker.

3

Stai elaborando sullo stesso thread che gestisce la GUI? Potresti voler esaminare un thread SwingWorker per eseguire lo stuffing pesante sullo sfondo in modo che l'UI resti reattivo in tal caso.

+0

Questo è esattamente quello che sto facendo e vedo cosa sto sbagliando. Devo solo provare a capire l'implementazione di un'altra discussione ora. – JTApps

3

Sì, è perché hai bloccato con EDT con gli altri tuoi metodi.

È necessario utilizzare un altro Thread per eseguire il lavoro in background altrimenti la GUI verrà bloccata.

Nelle applicazioni Swing è consigliabile eseguire qualsiasi operazione di lunga durata su un SwingWorker.

Dai uno sguardo allo documentation per un'introduzione.

A SwingWorker eseguirà un'attività che viene fornita e può segnalare alla GUI quando viene eseguita. Questo sarà fatto in un modo non bloccante in modo che tu possa ancora usare la GUI mentre il compito viene eseguito.

Se si desidera poter annullare l'attività in background, è necessario mantenere un riferimento allo SwingWorker in modo da poter chiamare il metodo cancel. In questo caso il metodo di lavoro deve essere interrompibile, altrimenti l'attività non può essere annullata.

+0

In questo caso, Annulla semplicemente uscirà completamente dal programma anziché interromperlo. Il modo in cui le varie risposte lo fanno sembrare, sembra che potrebbe richiedere una ristrutturazione del codice principale che NON voglio fare. Potrei interpretarlo male, però. Stai suggerendo essenzialmente di includere tutto il codice del listener di azioni che non è correlato alla GUI usando SwingWorker? – JTApps

+0

Sì, questo è quello che dovresti fare. Se si desidera fornire gli aggiornamenti della GUI mentre avviene l'elaborazione, si pubblicano gli aggiornamenti utilizzando il metodo 'publish' e si sovrascrive il metodo' process'. Il metodo 'process' verrà eseguito sull'EDT, quindi non interrompe il modello a thread singolo di Swing. –

+0

Sto facendo le mie ricerche ora, ma ho un po 'di problemi con la logica. Ad esempio, se volessi fare 'cancelButton.setEnabled (true)' mentre esegui il metodo 'doSomething()', come sarebbe? Una rappresentazione visiva della logica qui mi aiuterebbe ad applicarla al meglio. – JTApps

Problemi correlati