【问题标题】:popUpMenuPositioningItem:atLocation:inView: hangs when switching to another applicationpopUpMenuPositioningItem:atLocation:inView: 切换到另一个应用程序时挂起
【发布时间】:2011-04-02 04:43:14
【问题描述】:

我正在开发一个无坞站应用程序 (LSUIElement true)。当用户点击相应的NSStatusItem 或使用键盘快捷键时,应用程序会弹出一个菜单。

我的问题是,每当用户切换到另一个应用程序(使用 ⌘-TAB)而不先关闭菜单时,所有弹出菜单的方法都会以编程方式挂起。我试过popUpMenuPositioningItem:atLocation:inView:popUpContextMenu:withEvent:forView:,以及NSStatusItempopUpStatusItemMenu:)上对应的方法。

如果用户使用 ESC 键关闭菜单一切正常,但如果用户切换到不同的应用程序,上述方法永远不会返回(它们似乎同步运行并在菜单关闭时返回)。应用程序不会崩溃,并且有一些技巧可以重新获得控制权(调用 exposé,或单击任何弹出菜单的NSStatusItem)。

如果应用程序有停靠图标(即将LSUIElement 设置为 false),问题就会消失。

这是使用键盘快捷键时弹出菜单的代码:

[mainMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0]
                        atLocation:[NSEvent mouseLocation]
                            inView:nil];

这是点击NSStatusItem时弹出菜单的代码:

- (void)mouseDown:(NSEvent *)event
{
    [statusItem popUpStatusItemMenu:[statusItem menu]];
}

mouseDown: 方法在附加到 NSStatusItem 的自定义 NSView 中。

知道如何解决这个问题吗?

感谢您的帮助。

更新

该问题还与正在激活的应用程序有关(我在显示菜单之前使用[NSApp activateIgnoringOtherApps:YES];,或者在某些情况下无法使用键盘导航菜单)。

【问题讨论】:

    标签: objective-c macos cocoa menu


    【解决方案1】:

    问题似乎是由于应用程序激活和 popUpMenu 发生在同一个事件周期中。我找到了一种解决方法,在this post 中有更详细的描述。

    总结一下,你需要先激活应用程序(使用[NSApp activateIgnoringOtherApps:YES];),然后弹出菜单,确保这发生在一个新的事件循环中:你可以使用NSTimer触发菜单来实现。

    - (void) someMethod {
        // Some code
        [NSApp activateIgnoringOtherApps:YES];
        [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showMenu) userInfo:nil repeats:NO];
        //Some other code
    }
    
    - (void) showMenu {
        // This will show the menu at the current mouse position
        [aMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0] atLocation:[NSEvent mouseLocation] inView:nil];
    }
    

    【讨论】:

    • 如果我只睡 0.01 而不是计划计时器,它也可以吗?
    猜你喜欢
    • 2017-01-30
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 2018-09-06
    相关资源
    最近更新 更多