2010-12-10 11 views
5

Ho un'applicazione di GUI bancaria a cui sto lavorando attualmente e sembra che ci sia un problema con il metodo setvisible per il mio jdialog. Dopo che l'utente ha ritirato un importo valido, faccio apparire una semplice finestra di dialogo che dice "transazione in corso". Nel mio metodo dobackground tengo il polling per verificare se la transazione è stata ricevuta. Ho provato ad usare Swingworker e non capisco perché non funzioni. Se rimuovo la chiamata setvisibile funziona bene, quindi perché setvisible fa sì che il sistema si blocchi? Ecco il codice che è dentro il mio JButton MouseListener:metodo setvisible nel sistema di sospensione java

SwingWorker<String,Integer> worker = new SwingWorker<String,Integer>(){ 

    JDialog waitForTrans = new JDialog((JFrame)null,true); 
    public String doInBackground() throws Exception { 
    waitForTrans.add(new JLabel("Updating balance in system. Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300,100)); 
    waitForTrans.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    waitForTrans.setVisible(true); 
    Bank.getInstance().sendTransaction(currentPin,"-"+withdraw); 
    while(!Bank.getInstance().hasCompletedTransaction){ 

    } 
    return null; 

    } 

    public void done(){ 
    try { 
     this.get(); 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 

     e.printStackTrace(); 
    } 
    waitForTrans.setVisible(false); 
    newField.setText(String.valueOf(Bank.getInstance().getAccountList().get(currentPin).getBalance())); 
    } 

}; 
worker.execute(); 
+0

Quale versione di java hai visto questo blocco? Abbiamo aggiornato da java 6 a java 8 e potrebbe essere in esecuzione in questo comportamento. – simgineer

risposta

13

Prima di tutto, si consiglia di eseguire tutti gli aggiornamenti della GUI nel thread di evento-invio di Swing, ovvero utilizzando la classe SwingUtilites.

In secondo luogo, il tuo JDialog è modale e quindi blocca il thread in cui viene chiamato il metodo setVisible(true) (nel tuo caso il thread principale, nel caso seguente il thread di invio eventi di Swing).

non dico il seguente codice è perfetto, ma dovrebbe mettere in pista ...

 

final JDialog waitForTrans = new JDialog((JFrame) null, true); 

SwingWorker worker = new SwingWorker() { 

    public String doInBackground() throws Exception { 
    Thread.sleep(5000); 
    return null; 
    } 

    public void done() { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     waitForTrans.setVisible(false); 
     waitForTrans.dispose(); 
     } 
    }); 
    } 

}; 

worker.execute(); 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    waitForTrans.add(new JLabel("Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300, 100)); 
    waitForTrans.setVisible(true); 
    } 
}); 
 

Spero che questo aiuti.

+0

Grazie per le risposte veloci! Sono ancora un po 'traballante su questo tipo di aspetti della programmazione di gui, ma ora lo trovo per la maggior parte ... – Adith

+0

Capire come funziona la discussione di evento-spedizione di Swing e come usarla nel modo giusto è stata la parte più difficile della GUI Swing per me. Prenditi il ​​tuo tempo e fallo bene, ti farà risparmiare un sacco di problemi in seguito. –

+1

Il metodo done viene eseguito sul thread di invio eventi, quindi non penso che sia necessario utilizzare SwingUtilities.invokeLater in tale metodo. Vedi http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#done%28%29 – Ryan

5

si sta visualizzando una finestra di dialogo modale in modo che il codice di fondo non può eseguire fino a quando la finestra è chiusa.

Aggiungi un'istruzione System.out.println (...) dopo setVisible e vedrai che non viene mai eseguita.

+0

Sì, vedo il tuo punto. Grazie per l'aiuto. – Adith

0

camickr fornisce la risposta corretta. Voglio aggiungere che vietato modificare l'interfaccia utente al di fuori del filo Event spedizione (come si fa in #doInBackground), Swing è unico thread in modo da violare questa regola potrebbe portare a bug molto difficili e cose strane nella vostra interfaccia utente.

1

setVisiblesetVisible è un metodo che influisce sulla GUI, causando la visualizzazione di qualcosa (e, nel caso di una finestra di dialogo modale come la vostra, bloccare fino a quando la finestra di dialogo non viene chiusa). Esso (come tutto il resto che modifica l'interfaccia utente visibile) deve essere mai chiamato tranne nel thread di invio dell'evento Swing. Lo chiami dal metodo doInBackground di SwingWorker, che viene eseguito su un thread in background.

che cosa dovete fare per risolvere questo problema è rendere il waitForClose dialogo una variabile final che si crea prima di chiamare execute sulla SwingWorker e quindi chiamare setVisible immediatamente dopo partenza il lavoratore.

final JDialog waitForTrans = ... 
// set up the dialog here 

SwingWorker<String, Integer> worker = new SwingWorker<String, Integer>() { 
    ... 
}; 
worker.execute(); // start the background process 

waitForTrans.setVisible(true); // show the dialog 

È necessario farlo in questo ordine perché altrimenti la finestra di dialogo modale bloccherà l'avvio del lavoratore.

Problemi correlati