2011-11-08 5 views
11

मैं ग्रैंड सेंट्रल डिस्पैच का उपयोग करके असीमित रूप से चल रहे कुछ लंबे फ़ंक्शन की प्रगति दिखाने के लिए, एक प्रगति पट्टी वाली विंडो पर एक शीट प्रदर्शित करने का प्रयास कर रहा हूं। मुझे लगभग यह मिल गया है, लेकिन शीट को फोकस में नहीं दिख सकता है, शायद इसलिए कि मैंने runModalForWindow: या इसी तरह का उपयोग नहीं किया है।ग्रैंड सेंट्रल डिस्पैच का उपयोग करते समय सामान्य रूप से "प्रगति" शीट को सही तरीके से प्रदर्शित करने के लिए कैसे करें?

यह लगभग क्या मैं इस समय कर रहा हूँ है, यह मुख्य विंडो पर एक बटन प्रेस का एक परिणाम के रूप में होता है:

// Prepare sheet and show it... 

    [NSApp beginSheet:progressSheet modalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL]; 

    [progressSheet makeKeyAndOrderFront:self]; 

    [progressBar setIndeterminate:NO]; 
    [progressBar setDoubleValue:0.f]; 
    [progressBar startAnimation:self]; 


    // Start computation using GCD... 

    dispatch_async(dispatch_get_global_queue(0, 0), ^{ 

     for (int i = 0; i < 1000; i ++) { 
      // Do some large computation here 
      // ... 

      // Update the progress bar which is in the sheet: 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [progressBar setDoubleValue:(double)i]; 
      }); 
     } 


     // Calculation finished, remove sheet on main thread 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      [progressBar setIndeterminate:YES]; 

      [NSApp endSheet:progressSheet]; 
      [progressSheet orderOut:self]; 
     }); 
    }); 

यह काम करता है मुख्य विंडो को छोड़कर, ध्यान में अब भी है शीट फोकस से बाहर है, और प्रगति पट्टी एनिमेट नहीं करती है (जब तक कि मैं setUsesThreadedAnimation:YES पर इसका उपयोग नहीं करता)।

मुझे लगता है कि मुझे लगता है कि समस्या यह है कि मुझे एसिंक्रोनस गणना शुरू करने से पहले मुख्य धागे को अवरुद्ध किए बिना शीट को सामान्य रूप से चलाने का तरीका नहीं है?

+0

विंडो के लिए शीट को सामान्य रूप से चलाना मुख्य धागे को अवरुद्ध नहीं करना चाहिए (अन्यथा आपके '-बेजिन शीट के बाद कुछ नहीं: विधि की शुरुआत में थोड़ा सा निष्पादित होगा)। मैं यहां अपने आवेदन में लगभग इसी तरह का उपयोग करता हूं (आपके द्वारा प्रस्तुत की गई मॉडल शीट, इसके बारे में प्रगति पट्टी के साथ), और यह पृष्ठभूमि में चलने वाले जीसीडी ब्लॉक से ठीक ठीक है। जिस शीट से नीचे स्लाइड की गई खिड़की पर नियंत्रण गहरा हुआ है, यह दर्शाता है कि खिड़की शीट पर ध्यान केंद्रित कर चुकी है, इसलिए यह सामान्य लगता है। क्या मुख्य धागे पर बहुत सी कार्रवाइयों को कतारबद्ध किया जा सकता है? –

+0

@ ब्रैडलर्सन एकमात्र अन्य चीज जिसे मैं सोच सकता हूं, मुख्य गणना के हिस्से के रूप में समस्याएं 'प्रेषण_प्ली' थीं, लेकिन इसे मानक लूप के साथ बदलने से कोई फर्क नहीं पड़ता। अन्यथा, मुख्य धागे पर कुछ और नहीं चल रहा है। मैं अभी भी मुख्य खिड़की पर शीट के पीछे नियंत्रण के साथ बातचीत कर सकता हूं, और वे अभी भी फोकस में दिखाई देते हैं (यानी, बाहर ग्रे नहीं)। उदाहरण के लिए मुख्य विंडो पर एक टेक्स्ट बॉक्स, जबकि शीट प्रदर्शित की जा रही है, फोकस रिंग के साथ दिखाई देती है और मैं अभी भी इसमें टेक्स्ट दर्ज कर सकता हूं (हालांकि मैं माउस के साथ टेक्स्ट का चयन नहीं कर सकता)। – Robert

उत्तर

2

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

मैंने उस कारण से टाइटल बार बंद कर दिया, लेकिन किसी भी तरह इसे ध्यान से सही ढंग से प्राप्त करने की आवश्यकता है। शीर्षक बार चेकबॉक्स चेकिंग मेरे प्रगति बार शीट फोकस देता है।

+0

हाँ, मेरी खिड़की में शीर्षक बार नहीं था, और यह मेरे लिए समस्या तय कर रहा था। – Robert

4

जैसा कि ब्रैड ने कहा है, इसे काम करना चाहिए।

एक त्वरित परीक्षण करने के लिए, मैंने प्रोग्रामेटिक रूप से एक शीट बनाई (आमतौर पर, आप शायद एक निब फ़ाइल का उपयोग करेंगे, लेकिन उन्हें इस पाठ में पेस्ट करना मुश्किल है)। अगर मैं सामान्य कोको विंडो में बटन से नीचे कोड को कॉल करता हूं, तो यह अपेक्षित काम करता है। ध्यान दें कि शीट पर टेक्स्ट फ़ील्ड पहला प्रतिसादकर्ता है, और यदि आप खुले होने पर कीबोर्ड पर टाइप करते हैं, तो यह इनपुट स्वीकार करेगा। बदसूरत शीट के लिए

#define maxloop 1000 

- (IBAction)startTask:(id)sender 
{ 
    // Prepare sheet and show it... 

    breakLoop = NO; 

    NSRect sheetRect = NSMakeRect(0, 0, 400, 114); 

    NSWindow *progSheet = [[NSWindow alloc] initWithContentRect:sheetRect 
                 styleMask:NSTitledWindowMask 
                 backing:NSBackingStoreBuffered 
                  defer:YES]; 

    NSView *contentView = [[NSView alloc] initWithFrame:sheetRect]; 

    NSProgressIndicator *progInd = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(143, 74, 239, 20)]; 

    NSTextField *inputField = [[NSTextField alloc] initWithFrame:NSMakeRect(145, 48, 235, 22)]; 

    NSButton *cancelButton = [[NSButton alloc] initWithFrame:NSMakeRect(304, 12, 82, 32)]; 
    cancelButton.bezelStyle = NSRoundedBezelStyle; 
    cancelButton.title = @"Cancel"; 
    cancelButton.action = @selector(cancelTask:); 
    cancelButton.target = self; 

    [contentView addSubview:progInd]; 
    [contentView addSubview:inputField]; 
    [contentView addSubview:cancelButton]; 

    [progSheet setContentView:contentView]; 


    [NSApp beginSheet:progSheet 
     modalForWindow:self.window 
     modalDelegate:nil 
     didEndSelector:NULL 
      contextInfo:NULL]; 

    [progSheet makeKeyAndOrderFront:self]; 

    [progInd setIndeterminate:NO]; 
    [progInd setDoubleValue:0.f]; 
    [progInd startAnimation:self]; 


    // Start computation using GCD... 

    dispatch_async(dispatch_get_global_queue(0, 0), ^{ 

     for (int i = 0; i < maxloop; i++) { 

      [NSThread sleepForTimeInterval:0.01]; 

      if (breakLoop) 
      { 
       break; 
      } 

      // Update the progress bar which is in the sheet: 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [progInd setDoubleValue: (double)i/maxloop * 100]; 
      }); 
     } 


     // Calculation finished, remove sheet on main thread 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      [progInd setIndeterminate:YES]; 

      [NSApp endSheet:progSheet]; 
      [progSheet orderOut:self]; 
     }); 
    }); 
} 

- (IBAction)cancelTask:(id)sender 
{ 
    NSLog(@"Cancelling"); 
    breakLoop = YES; 
} 

क्षमा याचना, लेकिन अलग इस कोड अपेक्षित ढंग से काम करता है, इसलिए इस मुद्दे को आप देख रहे हैं शायद GCD से संबंधित नहीं है कि से।