2012-10-29 18 views
5

Avevo bisogno di un modo per ottenere alcuni dati da un database e impedire all'utente di modificare i dati esistenti per quel momento.JDialog modale in modo sicuro di apertura e chiusura (utilizzando SwingWorker)

Ho creato uno SwingWorker per effettuare l'aggiornamento del database e un JDialog modale per mostrare all'utente cosa sta succedendo (con un JProgressBar). La finestra di dialogo modale ha defaultCloseOperation impostato su DO_NOTHING, quindi può essere chiuso solo con una chiamata corretta - Io uso setVisible(false).

MySwingWorkerTask myTask = new MySwingWorkerTask(); 
myTask.execute(); 
myModalDialog.setVisible(true); 

Lo SwingWorker fa alcune cose all'interno doInBackground() e, infine, si chiama:

myModalDialog.setVisible(false); 

La mia unica preoccupazione e la mia domanda: È possibile che lo SwingWorker esegue il setVisible(false) prima che sia setVisible(true) in la linea dopo la generazione del lavoratore?

Se così il setVisible(true) potrebbe bloccare per sempre (l'utente non può chiudere la finestra modale).

Devo implementare qualcosa come:

while (!myModalDialog.isVisible()) { 
    Thread.sleep(150); 
} 
myModalDialog.setVisible(false); 

per assicurarsi che sarà effettivamente ottenere chiuso?

+1

si dovrebbe chiamare 'myModalDialog.setVisible (false);' in 'fatto()' invece di 'doInBackground()'. Perché non chiamate 'setVisible (true)' prima di 'execute'? – assylias

+0

setVisible (true) è una chiamata bloccante – user1713059

+0

Haha - davvero un buon punto :-) – assylias

risposta

3

In generale, sì.

Quello che farei nel tuo metodo doInBackground è SwingUtilities.invokeLater per mostrare la finestra di dialogo e nel tuo metodo done nascondere la finestra di dialogo.

Questo dovrebbe significare che, anche se la finestra non lo rende allo schermo si guadagna un po 'più di controllo sul flusso ...

Il problema minore è che sei ora costretta a passare il finestra di dialogo per il lavoratore in modo che possa ottenere il controllo su di esso ...

public class TestSwingWorkerDialog { 

    public static void main(String[] args) { 
     new TestSwingWorkerDialog(); 
    } 
    private JDialog dialog; 

    public TestSwingWorkerDialog() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       MyWorker worker = new MyWorker(); 
       worker.execute(); 

      } 
     }); 
    } 

    public class MyWorker extends SwingWorker<Object, Object> { 

     @Override 
     protected Object doInBackground() throws Exception { 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        getDialog().setVisible(true); 
       } 
      }); 
      Thread.sleep(2000); 

      return null; 
     } 

     @Override 
     protected void done() { 
      System.out.println("now in done..."); 
      JDialog dialog = getDialog(); 
      // Don't care, dismiss the dialog 
      dialog.setVisible(false); 
     } 

    } 

    protected JDialog getDialog() { 
     if (dialog == null) { 

      dialog = new JDialog(); 
      dialog.setModal(true); 
      dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); 
      dialog.setLayout(new BorderLayout()); 
      dialog.add(new JLabel("Please wait...")); 
      dialog.setSize(200, 200); 
      dialog.setLocationRelativeTo(null); 

     } 

     return dialog; 
    } 

} 
+1

Qual è la differenza tra 'SwingUtilities.invokeLater' e' EventQueue.invokeLater'? – Mordechai

+1

Scusa se la mia domanda è sciocca, ma nel tuo esempio è garantito, che il metodo di esecuzione di invokeLater è sicuramente eseguito prima che il lavoro sia finito()? Mi sembra come se il problema principale del mio post rimanesse - la concorrenza tra loro incerta, ma posso sbagliarmi. – user1713059

+2

@ M.M. Non ce ne sono. SwingUtilities.invokeLater inoltra la chiamata a EventQueue.invokeLater. –