2009-07-29 10 views
7

Mam NSSegmentedControl na moim interfejsie użytkownika za pomocą 4 przycisków. Sterowanie jest podłączony do metody, która będzie wywołać różne sposoby w zależności od segmentu kliknięciu:Pokaż menu NSSegmentedControl po kliknięciu segmentu, pomimo ustawienia akcji

- (IBAction)performActionFromClick:(id)sender { 
    NSInteger selectedSegment = [sender selectedSegment]; 
    NSInteger clickedSegmentTag = [[sender cell] tagForSegment:selectedSegment]; 

    switch (clickedSegmentTag) { 
      case 0: [self showNewEventWindow:nil]; break; 
      case 1: [self showNewTaskWindow:nil]; break; 
      case 2: [self toggleTaskSplitView:nil]; break; 
      case 3: [self showGearMenu]; break; 
    } 
} 

Segment 4 posiada posiada menu z nim związane w sposobie awakeFromNib. Chciałbym, aby to menu było rozwijane, gdy użytkownik kliknie segment. W tym momencie spadnie on tylko wtedy, gdy użytkownik kliknie w menu przytrzymanie klawisza &. Z moich badań online wynika to z połączonej akcji.

Obecnie pracuję nad nim za pomocą kodu, aby uzyskać punkt początkowy kontroli segmentu i pojawia się menu kontekstowe za pomocą NSMenu's popUpContextMenu:withEvent:forView, ale jest to dość hacktastic i wygląda źle w porównaniu do standardowego zachowania o menu opuść się poniżej podzielonej na segmenty komórki kontrolnej.

Czy istnieje sposób, aby menu było rozwijane tak, jak powinno po pojedynczym kliknięciu, zamiast robić coś z hacky menu kontekstowego?

+0

W 10.10.2/Xcode 6.3 standardowe zachowanie menu jest zmniejszane, gdy użytkownik kliknie segment, do którego nie dołączono żadnej akcji; i wymagać kliknięcia i przytrzymania, gdy segment ma IBAction. Ponieważ twoje działanie to "menu pokazu", powinieneś móc je usunąć. –

+0

Jak dołączyć działania do poszczególnych segmentów? –

Odpowiedz

3

Nie jestem pewien jakiejkolwiek wbudowanej metody wykonania tej czynności (chociaż to naprawdę jest rażąca dziura w interfejsie API NSSegmentedControl).

Moja rekomendacja to kontynuowanie robienia tego, co robisz, wyskakując z menu kontekstowego. Jednak zamiast tylko za pomocą pochodzenie segmentowego kontrolki, można umieścić go bezpośrednio pod segmencie (jak chcesz), wykonując następujące czynności:

NSPoint menuOrigin = [segmentedControl frame].origin; 
menuOrigin.x = NSMaxX([segmentedControl frame]) - [segmentedControl widthForSegment:4]; 
// Use menuOrigin where you _were_ just using [segmentedControl frame].origin 

To nie jest doskonały i idealny, ale powinno to zadanie i nadać wygląd/zachowanie, którego oczekują użytkownicy.

(Tak na marginesie, NSSegmentedControl naprawdę potrzebuje metody -rectForSegment:)

+1

Uzgodniono, że jest całkiem kulawy, nie ma wbudowanego sposobu, aby to zrobić. Złożyłem to na Radar. Dupe away: http://openradar.appspot.com/radar?id=61419 –

2

widthForSegment: zwraca zero jeśli segment samochodowych rozmiarach. Jeśli nie jesteś zaniepokojony nieudokumentowanych API, istnieje rectForSegment:

  • (NSRect) rectForSegment: (NSInteger) Segment szkieletu wewnętrznego (NSRect) rama;

Ale odpowiedzi na oryginalne pytanie, łatwiejszy sposób, aby uzyskać menu pop-up natychmiast do podklasy NSSegmentedCell i zwraca 0 dla (ponownie, nieudokumentowane)

  • (podwójne) _menuDelayTimeForSegment: (NSInteger)człon;
14

Podklasa NSSegmentedCell, zastąp metodę poniżej i zastąp klasę komórki w IB. (Nie wymaga prywatnych interfejsów API).

- (SEL)action 
{ 
    //this allows connected menu to popup instantly (because no action is returned for menu button) 
    if ([self tagForSegment:[self selectedSegment]]==0) { 
     return nil; 
    } else { 
     return [super action]; 
    } 
} 
+1

Działa to świetnie. Zdecydowanie najczystsze rozwiązanie, jakie widziałem. Dzięki! – djeckhart

+2

Niezłe rozwiązanie. Jedna drobna sugestia: ustaw warunek if na "[self menuForSegment: [self selectedSegment]]! = Zero"; w ten sposób nie musisz ustawiać tagów. –

+1

Ten rodzaj działa świetnie. Jeśli segment nie jest jeszcze zaznaczony, kliknięcie go nic nie robi. Kliknięcia po wybraniu segmentu tworzą menu. Nie widzę, jak to działa dla was, bez zmiany tego zachowania. –

3

To jest wersja Swift odpowiedzi J Hoover i mod Adam Treble. Przesunięcie nie było tak intuicyjne, jak myślałem, więc mam nadzieję, że pomogę komuś innemu.

override var action : Selector { 
     get { 
      if self.menuForSegment(self.selectedSegment) != nil { 
       return nil 
      } 
      return super.action 
     } 
     set { 
      super.action = newValue 
     } 
    } 
+0

Zrobiłem to, ale z jakiegoś powodu metoda "get" nigdy nie jest wywoływana. –

Powiązane problemy