2012-03-15 24 views

risposta

22

Yup.

Il pulsante di azione chiamata

[NSMenu popUpContextMenu:menu withEvent:event forView:(NSButton *)sender]; 

dove menù - menu che si desidera mostrare mittente - il pulsante è stato fatto clic. evento: puoi creare un nuovo evento e mentre crei, specifica la posizione in cui desideri visualizzare il menu popup.

+0

provato ma il menu "pop-up" va un po 'in tutto il luogo. Voglio che appaia esattamente SOTTO il pulsante (ad esempio il menu "Nuova scheda", "Nuova finestra", ecc. In Google Chrome), ma questo sembra troppo ... alto ... –

+1

Ya. Come ho detto sopra, puoi specificare la posizione del menu popup (di cui deve essere mostrato) durante la creazione dell'evento. –

+0

OK. L'avevo capito. Pubblicherò la risposta completa alla mia unica domanda ... –

4

L'utilizzo di un menu di scelta rapida sulla chiamata all'azione non è un ottimo modo per farlo perché il menu non viene visualizzato fino a quando mouseUp - non viene visualizzato il comportamento del menu di trascinamento per il controllo &. L'esempio di ButtonMadness di Apple mostra come eseguire realmente questa operazione in una sottoclasse di NSButton, vedere DropDownButton. https://developer.apple.com/library/mac/samplecode/ButtonMadness/Introduction/Intro.html

Riassumendo che sottoclasse: creare un NSPopUpButtonCell con pullsDown impostato su YES & preferredEdge a NSMaxYEdge, copiare il menu per aggiungere un elemento di alto vuoto e impostarlo come menu del cellulare, il mouseDown chiamata [thePopUpCell performClickWithFrame: self.bounds Inview : self] e set self.needsDisplay

+0

Su 10.8 almeno il codice DropDownButton è difettoso. Per evidenziare il problema, compilare l'esempio ButtonMadness e fare clic su DropDownButton. Il menu verrà visualizzato: non selezionare un elemento. Ora fai clic sul pulsante di opzione 2: il menu è nascosto ma l'elemento della radio non è selezionato. Quindi fare nuovamente clic, il menu viene nuovamente visualizzato. un altro clic e si nasconde ecc. –

+2

Perché è necessario aggiungere l'elemento vuoto? Apprezzo che lo fai (non riuscendo ad aggiungerlo tronca il menu) ma non riesco a capire perché –

5

Come ho commentato, trovo che l'esempio ButtonMadness non sia perfetto. La mia implementazione sembra funzionare meglio. Il menu viene visualizzato con il mouse in basso, il pulsante rimane premuto per tutto il tempo, la posizione del menu può essere specificata e il menu viene eliminato senza successiva visualizzazione spuria.

Per essere onesti, NSPopupButton è una scelta migliore nella maggior parte delle situazioni. Uso questo codice principalmente per la comodità di avere una classe per pulsanti e popup e perché il menu non contiene l'immagine di controllo popup e il titolo. Carico il menu da un pennino separato e riuso come è altrove nell'app, come richiesto.

Si noti che è banale aggiungere ulteriore supporto per dire un popover e un menu.

NSButton subclass: 

- (void)mouseDown:(NSEvent *)theEvent { 

    // if a menu is defined let the cell handle its display 
    if (self.menu) { 
     if ([theEvent type] == NSLeftMouseDown) { 
      [[self cell] setMenu:[self menu]]; 
     } else { 
      [[self cell] setMenu:nil]; 
     } 
    } 

    [super mouseDown:theEvent]; 
} 

NSButtonCell subclass: 

- (BOOL)trackMouse:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp 
{ 
    // if menu defined show on left mouse 
    if ([event type] == NSLeftMouseDown && [self menu]) { 

     NSPoint result = [controlView convertPoint:NSMakePoint(NSMidX(cellFrame), NSMidY(cellFrame)) toView:nil]; 

     NSEvent *newEvent = [NSEvent mouseEventWithType: [event type] 
               location: result 
              modifierFlags: [event modifierFlags] 
               timestamp: [event timestamp] 
              windowNumber: [event windowNumber] 
               context: [event context] 
              eventNumber: [event eventNumber] 
              clickCount: [event clickCount] 
               pressure: [event pressure]]; 

     // need to generate a new event otherwise selection of button 
     // after menu display fails 
     [NSMenu popUpContextMenu:[self menu] withEvent:newEvent forView:controlView]; 

     return YES; 
    } 

    return [super trackMouse:event inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp]; 
} 
+0

funziona alla grande per me. Ho trovato che posso impostare il menu direttamente sulla cella e non c'è bisogno di sottoclasse del pulsante. Mi manca qualche ragione questo sarebbe un problema? –

4

Recentemente, stavo cercando di attuarlo e sono venuto, come penso, con una soluzione più semplice

-(IBAction)buttonClick:(id)sender { 
    NSButton * b = (NSButton*)sender; 
    NSPoint l = [ self.window convertBaseToScreen:b.frame.origin ]; 

    [ self.menu popUpMenuPositioningItem:nil atLocation:l inView:nil ]; 
} 

Aggiornamento

convertBaseToScreen è deprecato a partire da 10,7, invece di usa convertRectToScreen nel modo seguente:

NSPoint l = [self.window convertRectToScreen:b.frame].origin; 
+0

Bello un semplice, questo ha funzionato bene. –

+1

convertBaseToScreen è obsoleto dal 10_7 –

+0

Con storyboard (in un ViewController) non sembra funzionare. Ho provato senza successo: 'NSPoint point = [[self.view window] convertRectToScreen: ((NSButton *) mittente) .frame] .origin;' qualche idea? – Joannes

5

versione Swift di risposta accettata

@IBAction func actionOccurred(sender: NSButton) { 
    if let event = NSApplication.sharedApplication().currentEvent { 
     NSMenu.popUpContextMenu(sender.menu!, withEvent: event, forView: sender) 
    } 
} 
Problemi correlati