2011-11-08 26 views
11

Tôi đang cố gắng hiển thị một trang tính trên cửa sổ chứa một thanh tiến trình, để hiển thị tiến trình của một số chức năng dài chạy không đồng bộ bằng cách sử dụng Grand Central Dispatch. Tôi đã gần như có nó, nhưng không thể có được tờ để xuất hiện để được tập trung, có lẽ bởi vì tôi đã không sử dụng runModalForWindow: hoặc tương tự.Làm thế nào để hiển thị chính xác bảng "tiến bộ" trong khi sử dụng Grand Central Dispatch để xử lý nội dung nào đó?

Đây là khoảng những gì tôi đang làm vào lúc này, nó sẽ xảy ra như là kết quả của một nút bấm trên cửa sổ chính:

// 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]; 
     }); 
    }); 

này hoạt động, ngoại trừ cửa sổ chính vẫn là ở tập trung, các trang tính nằm ngoài tiêu điểm và thanh tiến trình không hoạt ảnh (trừ khi tôi sử dụng setUsesThreadedAnimation:YES trên đó).

Sự cố tôi nghĩ là tôi không chắc chắn cách chạy trang tính một cách hợp lý mà không chặn luồng chính trước khi tôi bắt đầu tính toán không đồng bộ?

+0

Chạy trang tính theo phương thức cho cửa sổ sẽ không chặn luồng chính (nếu không thì không có gì sau bit '-beginSheet:' của bạn ở đầu phương thức sẽ thực thi). Tôi sử dụng một cái gì đó gần như giống hệt với điều này (tờ phương thức trình bày như bạn làm, với một thanh tiến trình trên nó) trong ứng dụng của tôi ở đây, và nó cập nhật tốt từ một khối GCD chạy trong nền. Các điều khiển trên cửa sổ tờ giấy trượt xuống được chuyển sang màu xám, cho biết cửa sổ đã mất tập trung vào trang tính, vì vậy điều đó có vẻ bình thường. Có thể có cái gì khác xếp hàng lên rất nhiều hành động trên các chủ đề chính? –

+0

@BradLarson Điều duy nhất tôi có thể nghĩ rằng có thể gây ra vấn đề là một 'dispatch_apply' như là một phần của tính toán chính, nhưng thay thế nó bằng một vòng lặp tiêu chuẩn không tạo ra bất kỳ sự khác biệt nào. Nếu không, có khá nhiều thứ khác không chạy trên luồng chính. Tôi vẫn có thể chủ yếu tương tác với các điều khiển trên cửa sổ chính, phía sau trang tính và chúng vẫn xuất hiện trong tiêu điểm (nghĩa là, không chuyển sang màu xám). Một hộp văn bản trên cửa sổ chính chẳng hạn, trong khi trang tính đang được hiển thị, xuất hiện với một vòng lấy nét và tôi vẫn có thể nhập văn bản vào nó (mặc dù tôi không thể chọn văn bản bằng chuột). – Robert

Trả lời

2

Tôi đã gặp sự cố tương tự. Với một số thử và sai, tôi đã tìm ra giải pháp. Hãy chắc chắn rằng cửa sổ trang tính của bạn là (a) NSWindow không phải là NSPanel (điều này có thể không quan trọng) và cửa sổ có Thanh Tiêu đề (vì đó là trang tính bạn đang sử dụng) sẽ không được hiển thị.

Tôi đã tắt Thanh tiêu đề vì lý do đó, nhưng bằng cách nào đó, nó được yêu cầu để đạt được tiêu điểm chính xác. Đánh dấu vào hộp kiểm Thanh Tiêu đề cho tập trung vào thanh tiến trình của tôi.

+0

Đúng, cửa sổ của tôi không có thanh tiêu đề, việc thêm nó đã khắc phục sự cố cho tôi. – Robert

4

Như đã nêu bởi Brad, nó sẽ hoạt động.

Để thực hiện kiểm tra nhanh, tôi đã tạo một trang tính theo chương trình (thông thường, bạn có thể sử dụng tệp nib nhưng chúng rất khó dán vào văn bản này). Nếu tôi gọi mã dưới đây từ một nút trong một cửa sổ Cocoa bình thường, nó hoạt động như mong đợi. Lưu ý rằng trường văn bản trên trang tính là trả lời đầu tiên, và nếu bạn gõ trên bàn phím trong khi nó đang mở, nó sẽ chấp nhận đầu vào.

#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; 
} 

Xin lỗi cho tấm xấu xí, nhưng ngoài việc đó mã này làm việc như mong đợi, vì vậy vấn đề bạn đang nhìn thấy có lẽ không liên quan đến GCD.

Các vấn đề liên quan