2012-10-29 62 views
5

我需要一種方法從數據庫獲取一些數據,並防止用戶在那一刻修改現有數據。安全地打開和關閉模式JDialog(使用SwingWorker)

我創建了一個SwingWorker來創建數據庫更新和一個模態JDialog,以顯示用戶正在進行的操作(使用JProgressBar)。模態對話框的defaultCloseOperation設置爲DO_NOTHING,因此只能通過正確的呼叫關閉 - 我使用setVisible(false)

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

的SwingWorker的做一些事情中doInBackground(),最後調用:

myModalDialog.setVisible(false); 

我唯一擔心的,我的問題: 是可能的SwingWorker的執行setVisible(false)之前,它是setVisible(true)在工人產卵後的生產線?

如果是這樣,setVisible(true)可能會永遠阻塞(用戶無法關閉模式窗口)。

我一定要實現的東西如:

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

,以確保它真正能拿到關閉?

+1

你應該叫'myModalDialog.setVisible(假);''中'做的(),而不是'doInBackground()'。你爲什麼不在'execute'之前調用'setVisible(true)'? – assylias

+0

setVisible(true)是一個阻止呼叫 – user1713059

+0

哈哈 - 非常好的一點確實:-) – assylias

回答

3

一般來說,是的。

我會做的是在你的doInBackground方法是用SwingUtilities.invokeLater來顯示對話框並在你的done方法中隱藏對話框。

這應該意味着,即使對話沒有使它的屏幕上,你獲得更多的控制在流...

次要問題是你現在將不得不通過對話框的工人,因此能獲得控制權...

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

'SwingUtilities.invokeLater'和'EventQueue.invokeLater'有什麼區別? – Mordechai

+1

對不起,如果我的問題很愚蠢,但在你的例子中它是有保證的,invokeLater的run方法肯定是在工作完成之前運行的()?對我來說,似乎我的帖子的主要問題仍然存在 - 主觀上不確定的併發性,但我可能是錯的。 – user1713059

+2

@ M.M。沒有了。 SwingUtilities.invokeLater將呼叫轉發給EventQueue.invokeLater。 –