Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 从NSB按钮弹出菜单实现_Objective C_Macos_Cocoa - Fatal编程技术网

Objective c 从NSB按钮弹出菜单实现

Objective c 从NSB按钮弹出菜单实现,objective-c,macos,cocoa,Objective C,Macos,Cocoa,我该怎么做呢 我在想 [NSMenu popUpContextMenu:menu withEvent:event forView:(NSButton *)sender]; 是的 按钮式动作呼叫 [NSMenu popUpContextMenu:menu withEvent:event forView:(NSButton *)sender]; 在哪里 菜单:要显示的菜单 发件人:您单击的按钮 事件:创建一个新的n事件 创建新的NSEvent时,指定要显示弹出菜单的位置。在操作调用上使用上下

我该怎么做呢

我在想

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

按钮式动作呼叫

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

  • 菜单
    :要显示的菜单
  • 发件人
    :您单击的按钮
  • 事件
    :创建一个新的
    n事件

创建新的
NSEvent
时,指定要显示弹出菜单的位置。

在操作调用上使用上下文菜单不是一个好方法,因为菜单直到鼠标点击后才会显示-您不会获得按住并拖动菜单行为。Apple的ButtonMaddess示例展示了如何在NSButton的子类中真正做到这一点,请参见DropDownButton


总结该子类:创建一个NSPopUpButtonCell,pullsDown设置为YES&preferredEdge设置为NSMaxYEdge,复制菜单添加一个空白的顶部项,并将其设置为该单元格的菜单,鼠标向下调用[thePopUpCell PerformicClickWithFrame:self.bounds inView:self]设置self.needsDisplay

正如我所评论的,我发现ButtonMaddess示例并不完美。 我的实现似乎工作得更好。在鼠标按下时显示菜单,按钮始终保持按下状态,可以指定菜单位置,菜单将被取消,而不会出现后续的虚假显示

老实说,在大多数情况下,按钮是一个更好的选择。我之所以使用这段代码,主要是因为有一个用于按钮和弹出窗口的类很方便,而且菜单不包含弹出控件图像和标题。我从一个单独的nib加载菜单,并根据需要在应用程序的其他地方重复使用它

请注意,添加对popover以及菜单的额外支持是很简单的

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

最近,我试图实现它,我想到了一个更简单的解决方案

-(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; 

公认答案的快速版本

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

最新答案 将NSMenu添加到故事板中的NSViewController,如图所示

连接插座 右键单击故事板中的按钮,并将菜单出口连接到我们刚刚添加到故事板的菜单(图像中箭头指向的位置)

添加IBAction 你喜欢那样做

    -(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]; 
     }

试过了,但是“弹出”菜单有点到处都是。我希望它出现在按钮的正下方(例如,像谷歌Chrome中的“新标签”、“新窗口”等菜单),但这一个也出现在按钮下方。。。高…耶。如上所述,您可以在创建事件时指定弹出菜单的位置(需要显示的位置)。您可以对事件使用[[NSApplication sharedApplication]currentEvent]。[self.myButton sendActionOn:NSLeftMouseDownMask]将在鼠标按下时触发此操作。我建议
-[NSMenu popup:…]
而不是类方法。这样,即使您使用键盘快捷键,它也将相对于您的按钮定位。在10.8上,至少DropDownButton代码有缺陷。要突出显示该问题,请构建ButtonMaddess示例并单击下拉按钮。菜单将显示-不要选择项目。现在单击单选按钮2-菜单隐藏,但未选择单选项。因此,再次单击,菜单将再次显示。另一个点击和隐藏。为什么你需要添加空白项目?我很感激您这么做(未能添加它会截断菜单),但我无法找出为什么ConvertBaseToScreen会被弃用,因为10_7带有故事板(在ViewController中)它似乎不起作用。我尝试了,但没有成功:
NSPoint point=[[self.view window]convertDirectToScreen:((NSButton*)sender.frame.)一些想法?@Joannes检查您是否已正确设置所有,即您的操作已连接并正在被调用,self.menu不是nil,self.view.window不是nil。你得到了什么价值(点)?对我来说很有用。我发现我可以直接在单元格上设置菜单,而不需要对按钮进行子类化。我是不是遗漏了什么原因,这会成为一个问题?
    -(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]; 
     }