【问题标题】:Is it possible to group items in a NSPopupButton?是否可以在 NSPopupButton 中对项目进行分组?
【发布时间】:2019-04-20 22:25:38
【问题描述】:

我正在尝试显示系统声音列表,但我想按地区对它们进行分组。

这是一个在 html 中选择的例子。

理想情况下,我想创建一个类似于无障碍语言选择的下拉菜单。

有没有办法在 Interface Builder / swift 中复制它? 任何指针将不胜感激。

更新:

这样做的原因是因为我正在向用户显示语音列表。目前,它将所有区域混合在一起,这非常混乱。

我正在处理一个更新,我可以在其中显示“英语(英国)”,但我想在发布之前将它们分组。

【问题讨论】:

  • 我认为没有这样的现成控件。不过,您应该能够使用表格视图来构建它。 (这些天我主要在 iOS 上工作,所以我的 Mac Cocoa 开始生锈了。)
  • @DuncanC 是对的。您的第二个屏幕截图似乎是模态表内显示的NSTableView。因此,如果这就是您要复制的内容,那么您应该从那里开始。
  • 进一步挖掘后,我发现不,NSTableView 确实 支持部分。我发现这个链接有人做了艰苦的工作:blog.krzyzanowskim.com/2015/05/29/…
  • 嗯,它支持分组行:developer.apple.com/documentation/appkit/nstableviewdelegate/…。 API 与 iOS 上的 API 不同(NSTableView 早于 UITableView),而且您可能会遇到困难,具体取决于您的数据结构
  • 我检查了 Accessibility Inspector,你第二张截图中的语音表是NSTableView

标签: swift xcode macos interface-builder


【解决方案1】:

以下代码组菜单,但不像你提到的那样。

let items = [["First","Second"],["First","Second"],["First","Second"]]

lazy var addNewViewButton : NSPopUpButton = {
    let popupButton = NSPopUpButton()

    let firstMenuItem = NSMenuItem(title: "First Group", action: nil, keyEquivalent: "")
    let secondMenuItem = NSMenuItem(title: "Second Group", action: nil, keyEquivalent: "")
    let thirdMenuItem = NSMenuItem(title: "Third Group", action: nil, keyEquivalent: "")

    let superMenu = NSMenu()
    superMenu.addItem(firstMenuItem)
    superMenu.addItem(secondMenuItem)
    superMenu.addItem(thirdMenuItem)

    for (index,item) in items.enumerated()
    {
        let menu = NSMenu()
        for title in item
        {
            let menuItem = NSMenuItem(title: title, action: nil, keyEquivalent: "")
            menuItem.target = self
            menu.addItem(menuItem)
        }
        menu.addItem(NSMenuItem.separator())
        superMenu.setSubmenu(menu, for: superMenu.items[index])
    }
    popupButton.menu = superMenu

    popupButton.translatesAutoresizingMaskIntoConstraints = false

    return popupButton
}()

在你的代码中添加弹出按钮,你会得到这样的结果

每个人都有自己的物品。

【讨论】:

  • 在这一点上,任何东西都比我现在拥有的要好。谢谢。
  • 菜单显示完美,但是每当我选择一个项目时,它默认返回到第一个条目。 :(
  • 我想通了。在这里查看我的答案:stackoverflow.com/questions/53465965/…
【解决方案2】:

如果没有分组标题,可以使用以下代码

let items = [["First","Second"],["First","Second"],["First","Second"]]

lazy var addNewViewButton : NSPopUpButton = {
    let popupButton = NSPopUpButton()

    let menu = NSMenu()
    for item in items
    {
        for title in item
        {
            let menuItem = NSMenuItem(title: title, action: nil, keyEquivalent: "")
            menuItem.target = self
            menu.addItem(menuItem)
        }
        menu.addItem(NSMenuItem.separator())
    }
    popupButton.menu = menu

    popupButton.translatesAutoresizingMaskIntoConstraints = false

    return popupButton
}()

结果:

【讨论】:

  • 我已经用我当前问题的图片更新了问题。希望您的其他答案更可取的原因是有道理的。
  • 感谢您指出 NSPopupButton 有一个 .menu!在我的特殊情况下,我被困在无法将分隔菜单项直接添加到弹出类 .addItem(withTitle:) 中,只需执行 popupButton.menu.addItem(NSMenuItem.separator()) 就足够了。
【解决方案3】:

我将在 Objective-C 中提供答案,因为我不了解 Swift。抱歉……不过,你应该可以很容易地翻译它,或者我相信这里有人可以做到。

所以,我通过使用以下方法创建 NSMenu 的子类来管理它:

@implementation MenuWithSections

- (NSMenuItem*)insertItemWithTitle:(NSString*)aString action:(SEL)aSelector keyEquivalent:(NSString*)keyEquiv atIndex:(NSInteger)index
{
    NSMenuItem * item;
    NSString * adjustedString;

    if ([aString isEqualToString:menuDividerString]) {
        NSMenuItem *separator = [NSMenuItem separatorItem];
        [self insertItem:separator atIndex:index];
        return separator;
    } else if ([aString hasPrefix:menuSectionHeaderPrefix]) {
        adjustedString = [[aString substringFromIndex:menuSectionHeaderPrefix.length] capitalizedString];
        NSMenuItem * sectionHead =  [[NSMenuItem alloc] initWithTitle:adjustedString
                                                           action:nil
                                                    keyEquivalent:@""];
        sectionHead.enabled = NO;
        sectionHead.indentationLevel = 0;
        [self insertItem:sectionHead atIndex:index];
        return sectionHead;
    } 

    item = [super insertItemWithTitle:aString action:aSelector keyEquivalent:keyEquiv atIndex:index];
    item.indentationLevel = 1;
    return item;
}

@end

menuDividerString 在我的例子中是 @"----",menuSectionHeaderPrefix 是 @"..";请参阅下面的示例。

要让它发挥作用,请做三件事:

  1. 在 IB 中,向下钻取弹出按钮直到看到其菜单,然后将菜单的类设置为“MenuWithSections”。 popup button drill-down

  2. 关闭弹出按钮的“自动启用”功能(在 IB 的“属性”选项卡中单击关闭,或以编程方式将其设置为 NO)

  3. 使用上述常量传入修改后的字符串以获得所需的效果。

换句话说,要获得您想要的问题外观,请像这样传递弹出按钮标题:

[self.popbutton addItemsWithTitles:@[ @"..swedish cars", @"Volvo", @"Saab", @"..German cars", @"Mercedes", @"Audi"]];

sectioned popup

或者如果您想在两组之间设置分隔线,请使用:

[self.popbutton addItemsWithTitles:@[ @"..swedish cars", @"Volvo", @"Saab", @"----", @"..German cars", @"Mercedes", @"Audi"]];

sectioned popup with divider

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    相关资源
    最近更新 更多