2010-10-17 17 views
6
// This is supposed to show a modal dialog and then hide it again. In practice, 
// this works about 75% of the time, and the other 25% of the time, the dialog 
// stays visible. 
// This is on Ubuntu 10.10, running: 
// OpenJDK Runtime Environment (IcedTea6 1.9) (6b20-1.9-0ubuntu1) 

// This always prints 
// setVisible(true) about to happen 
// setVisible(false) about to happen 
// setVisible(false) has just happened 
// even when the dialog stays visible. 

package modalproblemdemo; 

import java.awt.Frame; 
import javax.swing.JDialog; 
import javax.swing.SwingUtilities; 

public class Main { 
    public static void main(String[] args) { 
     final Dialogs d = new Dialogs(); 
     new Thread() { 
      @Override 
      public void run() { 
       d.show(); 
       d.hide(); 
      } 
     }.start(); 
    } 

    static class Dialogs { 
     final JDialog dialog; 

     public Dialogs() { 
      dialog = new JDialog((Frame) null, "Hello World", /*modal*/ true); 
      dialog.setSize(400, 200); 
     } 

     public void show() { 
      SwingUtilities.invokeLater(new Runnable() { public void run() { 
       dialog.setLocationRelativeTo(null); 
       System.out.println("setVisible(true) about to happen"); 
       dialog.setVisible(true); 
      }}); 
     } 

     public void hide() { 
      SwingUtilities.invokeLater(new Runnable() { public void run() { 
       System.out.println("setVisible(false) about to happen"); 
       dialog.setVisible(false); 
       System.out.println("setVisible(false) has just happened"); 
      }}); 
     } 
    } 
} 
+0

क्या आप संवाद को मोडल नहीं कर सकते? फिर आप इसे थ्रेड के साथ गड़बड़ किए बिना बंद कर सकते हैं। –

+0

यह भी देखें: http://stackoverflow.com/questions/3886264/non-blocking-modal-swing-progress-dialog – Zarkonnen

उत्तर

2

तो यह पता चला है कि जब आप दिखाते हैं तो क्या होता है()/सेट विज़िबल (सत्य) एक मोडल डायलॉग यह है कि एक दूसरा इवेंट प्रेषण लूप कॉल/शो के लिए कॉल के भीतर चलाया जाता है। एक बार जब आप इसके बारे में जानते हैं तो सही समझ में आता है। इसे ध्यान में रखते, मैं इस कोड के साथ समाप्त हो गया:

public void runBlockingTask(final String taskName, final BlockingTask bt) { 
    SwingUtilities.invokeLater(new Runnable() { public void run() { 
     new Thread("Worker Thread: " + taskName) { 
      @Override 
      public void run() { 
       bt.run(); 
       progressDialog.setVisible(false); 
      } 
     }.start(); 
    }}); 
    // NB This causes the event dispatch loop to be run inside this call, 
    // which is why we need to put everything after setVisible into an 
    // invokeLater. 
    progressDialog.setVisible(true); 
} 
+0

+1। समर्पण के लिए कोई बैज है? –

4

यह स्पष्ट रूप से कुछ प्रकार की दौड़ की स्थिति है। मुझे नहीं लगता कि यह एरिक रॉबर्टसन के जवाब के समान सरल है। संवाद का show() कोड काफी जटिल है, इसमें ईवेंट प्रेषण धागे से बुलाए जाने के लिए कुछ विशेष तर्क शामिल हैं और यह ईवेंट कतार में ईवेंट पोस्ट करता है। शायद जिस क्रम में घटनाएं पोस्ट की जाती हैं वह किसी भी तरह से थ्रेड देरी से प्रभावित होती है।

शायद आपको SwingUtilities.invokeAndWait() की आवश्यकता है, इस तरह आप setVisible(true) को setVisible(false) पर कॉल करने से पहले निष्पादन समाप्त कर चुके हैं। जैसा कि छोड़ें हेड ने इंगित किया, invokeAndWait संवाद बंद होने तक अवरुद्ध होगा।

और आपको इसकी आवश्यकता क्यों है?

संपादित करें:)

  1. आप कॉल d.show (कि पदों setVisible(true) घटना
  2. धागा तो डाल दिया है अनुसूचक द्वारा सोने और में EDT किक और क्रियान्वित करने शुरू होता है: यह क्या हो रहा है की मेरी परिदृश्य है पहली घटना
  3. EDT से पहले पहला काम समाप्त हो गया है बाहर निकाल और एक वास्तविक घटना है कि संवाद
  4. अपने धागा d.hide() कि पदों setVisible (गलत) घटना को निष्पादित करता है से पता चलता पोस्ट हो जाती है। धागा समाप्त हो गया है और
  5. में EDT किक EDT पहला काम समाप्त होने पर, घटना कतार में अपनी दिखा घटना डालता
  6. यह अगली घटना के लिए चला जाता है, और, देखा है, यह setVisible (गलत) घटना है!
  7. यह संवाद की पूरी स्थिति को गड़बड़ कर देता है और यह दृश्यमान और उत्तरदायी रहता है।

EDIT2: ऐसा लगता है कि ProgressMonitor ऐसी कार्यक्षमता है जिसे आप कार्यान्वित करने का प्रयास कर रहे हैं।

+0

शो में InvokeAndWait() मोडल संवाद को बंद होने के लिए अवरुद्ध करने के लिए अवरुद्ध करता है। मुझे लगता है कि ज़ारकोनेन सभी अतिरिक्त धागे से बचने की कोशिश कर रहा है। –

+0

@ स्किप हेड: हाँ, आप सही हैं। –

+0

मुझे उपयोगकर्ता को यह बताने के लिए कि "प्रोग्राम व्यस्त व्यस्त है, कृपया" कृपया प्रतीक्षा करें, प्रसंस्करण "मोडल संवाद के रूप में इसकी आवश्यकता है। कार्यक्रम व्यस्त होने पर उपयोगकर्ता को बटन क्लिक करने से रोकने के लिए इसे मॉडल करने की आवश्यकता होती है ('कारण तब ईडीटी और कार्यकर्ता थ्रेड दोनों राज्य में छेड़छाड़ करेंगे)। – Zarkonnen

1

आप इसे छिपाने के बजाय dispose() संवाद करने का प्रयास कर सकते हैं, लेकिन यदि आप इसे फिर से दिखाना चाहते हैं तो आपको इसे पुनर्निर्माण करने की आवश्यकता होगी।

0

setVisible (सही) और setVisible (गलत) के बीच एक छोटी सी सोने का समय (100ms) कुछ मामलों में समस्या का हल। https://bugs.openjdk.java.net/browse/JDK-5109571 और सेट दृश्यमान (झूठी) के बजाय निपटान का उपयोग करने का प्रयास करते समय, कोई रेस स्थिति

संबंधित मुद्दे

 संबंधित मुद्दे