如何更改/修改NSPopUpButton的显示标题

时间:2018-02-22 19:04:21

标签: swift cocoa appkit

我希望NSPopUpButton显示与所选菜单项标题不同的标题。

假设我有一个NSPopUpButton让用户选择一个货币列表,我怎么能让折叠/关闭按钮只显示货币缩写而不是所选货币的菜单标题(这是完整的货币名称)?

我想我可以在子类(NSPopUpButtonCell)中覆盖绘制并自己绘制整个按钮,但我现在更喜欢使用更轻量级的方法来重用系统的外观。

菜单项包含有关缩写的必要信息,因此这不是问题的一部分。

2 个答案:

答案 0 :(得分:3)

子类NSPopUpButtonCell,覆盖drawTitle(_:withFrame:in:)并使用您想要的标题调用super

override func drawTitle(_ title: NSAttributedString, withFrame frame: NSRect, in controlView: NSView) -> NSRect {
    var attributedTitle = title
    if let popUpButton = self.controlView as? NSPopUpButton {
        if let object = popUpButton.selectedItem?.representedObject as? Dictionary<String, String> {
            if let shortTitle = object["shortTitle"] {
                attributedTitle = NSAttributedString(string:shortTitle, attributes:title.attributes(at:0, effectiveRange:nil))
            }
        }
    }
    return super.drawTitle(attributedTitle, withFrame:frame, in:controlView)
}

以同样的方式,您可以覆盖intrinsicContentSize的子类中的NSPopUpButton。更换菜单,拨打super并重新放回原始菜单。

override var intrinsicContentSize: NSSize {
    if let popUpButtonCell = self.cell {
        if let orgMenu = popUpButtonCell.menu {
            let menu = NSMenu(title: "")
            for item in orgMenu.items {
                if let object = item.representedObject as? Dictionary<String, String> {
                    if let shortTitle = object["shortTitle"] {
                        menu.addItem(withTitle: shortTitle, action: nil, keyEquivalent: "")
                    }
                }
            }
            popUpButtonCell.menu = menu
            let size = super.intrinsicContentSize
            popUpButtonCell.menu = orgMenu
            return size
        }
    }
    return super.intrinsicContentSize
}

答案 1 :(得分:-1)

好的,所以我发现了如何修改标题。我创建了一个单元子类,我在其中覆盖基于所选项目设置标题。在我的例子中,我按照问题中的讨论来检查所代表的对象。

final class MyPopUpButtonCell: NSPopUpButtonCell {
override var title: String! {
    get {
       guard let selectedCurrency = selectedItem?.representedObject as? ISO4217.Currency else {
           return selectedItem?.title ?? ""
       }
           return selectedCurrency.rawValue
       }
       set {}
    }
}

然后在我的按钮子类中设置单元格(我使用xibs)

override func awakeFromNib() {
    guard let oldCell = cell as? NSPopUpButtonCell else { return }
    let newCell = MyPopUpButtonCell()
    newCell.menu = oldCell.menu
    newCell.bezelStyle = oldCell.bezelStyle
    newCell.controlSize = oldCell.controlSize
    newCell.autoenablesItems = oldCell.autoenablesItems
    newCell.font = oldCell.font
    cell = newCell
}

但缺点是我必须复制我在Interface Builder中配置的单元格的所有属性。我当然可以在Interface Builder中设置单元格类,这使得这一点变得多余。 / p>

我还没想到的一件事是我现在可以让按钮具有正确的内在内容大小。它仍然试图像最长的常规冠军一样宽。

我还没想到的第二件事是如何使用绑定工作。如果按钮内容是通过Cocoa Bindings提供的,那么我只能绑定contentValues,并且永远不会调用单元格的title属性。