如何在NSMenu打开时更新它?

10

我有一个包含动态添加的NSMenuItems的NSMenu。当NSMenu处于打开状态时,它无法正确刷新。我在NSEventTrackingRunLoopModes中调用NSMenu更新方法。

我已经实现了以下方法来更新NSMenu。

- (void)menuNeedsUpdate:(NSMenu *)menu {
for (NSInteger index = 0; index < count; index++)
    [self menu:menu updateItem:[menu itemAtIndex:index] 
                       atIndex:index 
                  shouldCancel:NO];
}

- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel`

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

我有一个类似的问题。我想在NSMenu打开时根据用户是否按下Option键来更新它。我需要的行为类似于Xcode在Product菜单打开时按下Option键所执行的操作。这是否可以使用内置的NSMenu方法完成? - pjg
3个回答

7

更新NSEventTrackingRunLoopMode中的菜单项解决了这个问题。


5
我正在计时器中动态地填充菜单项,但当菜单打开时,NSMenu没有更新。

请确保在相应的运行模式下触发计时器:

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

您目前可能只会在NSDefaultRunLoopMode模式下触发它。

1
我已经尝试使用NSRunLoopCommonModes,但在菜单打开时仍然存在刷新问题。 - Vinpai

1

你漏掉了一堆代码。但是,你不应该调用-menu:updateItem:atIndex:shouldCancel:。这是一个你应该实现的方法,框架会调用它。

此外,通常情况下,你只需要实现其中之一-menuNeedsUpdate:或者同时实现-numberOfItemsInMenu:-menu:updateItem:atIndex:shouldCancel:。实现所有三个方法没有太多意义。如果可以立即构建菜单,则实现前者。如果构建菜单需要一些时间,则实现后两个方法。

最后,所有这些方法都被记录为在“菜单即将显示时”调用。我并不惊讶它们在菜单打开时不会重复调用。

如果你知道菜单需要更新,可以尝试调用-[NSMenu update]。这可能会促使它调用你的委托方法。我非常确定你也可以直接调用NSMenuNSMenuItem上的方法来修改菜单,而无需等待调用委托。


“[NSMenu update]” 不会调用任何代理方法。我正在计时器中动态填充菜单项,但当它打开时,NSMenu不会更新。 - Vinpai
即使您在计时器响应中调用 -[NSMenu addItem:]-[NSMenuItem setTitle:] 等方法,菜单仍未更新?我确信我已经看到菜单在打开时更新,所以这是可能的。 - Ken Thomases
@KenThomases 第一方操作系统时钟可以做到这一点(如果显示秒数,则更加明显)。 - Eliza Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接