Реализация всплывающего меню от NSButton - PullRequest
14 голосов
/ 15 марта 2012

Как мне это сделать?

Я думал о ...

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

Ответы [ 6 ]

26 голосов
/ 15 марта 2012

Да.

На кнопку вызова действия

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

, где

  • menu: меню, которое вы хотите показать
  • sender: кнопка, которую вы нажали
  • event: новый NSEvent, который вы создаете

Когда вы создаете новый NSEvent, укажите место, где вы хотите отображать всплывающее меню.

10 голосов
/ 28 марта 2016

Свифт версия принятого ответа

@IBAction func actionOccurred(sender: NSButton) {
    if let event = NSApplication.sharedApplication().currentEvent {
        NSMenu.popUpContextMenu(sender.menu!, withEvent: event, forView: sender)
    }
}
6 голосов
/ 17 марта 2015

Недавно я пытался реализовать его, и мне пришло, как мне кажется, более простое решение

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

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

Обновление

convertBaseToScreen устарелоначиная с 10.7, вместо него используйте convertRectToScreen следующим образом:

NSPoint l = [self.window convertRectToScreen:b.frame].origin; 
6 голосов
/ 09 января 2014

Как я уже прокомментировал, я нахожу пример ButtonMadness менее совершенным. Моя реализация, кажется, работает лучше. Меню отображается при наведении мыши, кнопка остается нажатой в течение всего времени, позиция меню может быть задана, и меню закрывается без последующего ложного отображения.

Если честно, NSPopupButton - лучший выбор в большинстве ситуаций. Я использую этот код в основном из-за удобства наличия одного класса для кнопок и всплывающих окон, а также потому, что в меню нет изображения и заголовка всплывающего элемента управления. Я загружаю меню из отдельного пера и повторно использую его, как и в любом другом месте приложения.

Обратите внимание, что добавить дополнительную поддержку, например, для всплывающих окон и меню, довольно просто.

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];
}
4 голосов
/ 06 ноября 2012

Использование контекстного меню при вызове действия не является хорошим способом сделать это, потому что меню не отображается до mouseUp - вы не получаете поведение удержания и перетаскивания меню.Образец Apple ButtonMadness показывает, как на самом деле сделать это в подклассе NSButton, см. DropDownButton.https://developer.apple.com/library/mac/samplecode/ButtonMadness/Introduction/Intro.html

Подводя итог этому подклассу: создайте NSPopUpButtonCell с pullsDown, установленным в YES, и предпочитаемый край для NSMaxYEdge, скопируйте свое меню, чтобы добавить пустой верхний элемент и установите его в качестве меню этой ячейки при вызове mouseDown [thePopUpCell executeClickWithFrame:self.bounds inView: self] и установите self.needsDisplay

0 голосов
/ 27 апреля 2018

Делай так.

    -(IBAction)onClickSourceAdd:(id)sender {
       NSMenu *mainMenu = [NSApp mainMenu];
       NSMenu *sourceMenu = [[mainMenu itemAtIndex:2] submenu];
       NSMenu *addMenu = [[sourceMenu itemAtIndex:0] submenu];
       [NSMenu popUpContextMenu:addMenu 
               withEvent:[NSApp currentEvent] 
               forView:(NSButton *)sender]; 
     }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...