2012-01-29 19 views
17

Tworzę aplikację, która działa na pasku stanu. Po kliknięciu na element statusu pojawia się komunikat NSPopover.Transmitowanie NSP, gdy popover znajduje się na pasku stanu

Wygląda to tak:

enter image description here

Oto problem: chcę być „przejściowy”, czyli jeśli kliknę gdziekolwiek poza popover będzie zamknąć. I podczas gdy NSPopoverBehaviorTransient działa dobrze, gdy popover jest w oknie, nie działa, gdy jest na pasku stanu.

Jak mogę sam wdrożyć takie zachowanie?

Odpowiedz

28

Okazało się to być proste:

- (IBAction)openPopover:(id)sender 
{ 
    // (open popover) 

    if(popoverTransiencyMonitor == nil) 
    { 
     popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask handler:^(NSEvent* event) 
            { 
             [self closePopover:sender]; 
            }]; 
    } 
} 

- (IBAction)closePopover:(id)sender 
{ 
    if(popoverTransiencyMonitor) 
    { 
     [NSEvent removeMonitor:popoverTransiencyMonitor]; 

     popoverTransiencyMonitor = nil; 
    } 

    // (close popover) 
} 

Co nie było łatwe, jednak to, że istnieją problemy z nieprzyjemnych o pop popover z NSStatusItem (nie zachowują się zgodnie z oczekiwaniami podczas misji Kontrola została wywołana lub spacja została przełączona na okno pełnoekranowe). Musiałem zaimplementować niestandardowe okno, które zawsze unosi się nad NSStatusItem i zajmuje się przełączaniem na okno pełnoekranowe itp. Wydawało się łatwe, ale wyraźnie elementy statusu nie były zaprojektowane do czegoś takiego;)

+5

Aby zachować spójne zachowanie z elementami statusu systemu: 'addGlobalMonitorForEventsMatchingMask: NSLeftMouseDownMask | NSRightMouseDownMask' - tak, że kliknięcie prawym przyciskiem myszy zamyka również popover. – inket

7

Podejście to Używam jest podobna do powyższej odpowiedzi, ale mam wszystko połączone w jedną metodę, zamiast używać dwóch oddzielnych IBActions.

Najpierw Oświadczam następujące właściwości

@property (strong, nonatomic) NSStatusItem *statusItem; 
@property (strong, nonatomic) NSEvent *popoverTransiencyMonitor; 
@property (weak, nonatomic) IBOutlet NSPopover *popover; 
@property (weak, nonatomic) IBOutlet NSView *popoverView; 

następnie w awakeFromNib skonfigurować element paska stanu

- (void)awakeFromNib { 

    self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 

    self.statusItem.title = @"Title"; 
    self.statusItem.highlightMode = YES; 
    self.statusItem.action = @selector(itemClicked:); 
} 

zastosowaną metodą, która jest wywoływana, gdy element Pasek stanu kliknięciu

- (void)itemClicked:(id)sender { 

    [[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge]; 

    if (self.popoverTransiencyMonitor == nil) { 
     self.popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask) handler:^(NSEvent* event) { 
      [NSEvent removeMonitor:self.popoverTransiencyMonitor]; 
      self.popoverTransiencyMonitor = nil; 
      [self.popover close]; 
     }]; 
    } 
} 

powoduje, że popover pojawia się i zamyka również, gdy użytkownik kliknie poza widokiem.

Należy pamiętać, że w konstruktorze interfejsów należy ustawić zachowanie popover na Transient, aby popover zamknął się, gdy użytkownik kliknie element statusu.

Powiązane problemy