如何 change/modify NSPopUpButton 的显示标题
How do I change/modify the displayed title of an NSPopUpButton
我希望 NSPopUpButton
显示与所选菜单项标题不同的标题。
假设我有一个 NSPopUpButton
让用户选择货币列表,我怎样才能让 collapsed/closed 按钮只显示货币缩写而不是所选货币的菜单标题 (这是货币的全称)?
我想我可以重写子类(NSPopUpButtonCell
)中的绘制并自己绘制整个按钮,但我现在更喜欢重用系统外观的更轻量级的方法。
菜单项包含有关缩写的必要信息,因此这不是问题的一部分。
好的,所以我找到了如何修改标题。我创建了一个单元格 subclass ,我在其中覆盖了基于所选项目的标题设置。在我的例子中,我检查了问题中讨论的代表 object。
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 {}
}
}
然后在我的按钮 subclass 我设置单元格(我使用 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 中配置的单元格的所有属性。 我当然可以只设置单元格 class Interface Builder,这使它变得多余。
我还没有弄清楚的一件事 是我现在如何让按钮具有正确的固有内容大小。它仍然尝试与最长的常规标题一样宽。
我还没有弄清楚的第二件事 是如何使它与绑定一起工作。如果按钮内容是通过 Cocoa 绑定提供的,那么我只能绑定 contentValues,并且永远不会调用单元格的标题 属性。
子类 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)
}
以同样的方式,您可以在 NSPopUpButton
的子类中覆盖 intrinsicContentSize
。替换菜单,调用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
}
我希望 NSPopUpButton
显示与所选菜单项标题不同的标题。
假设我有一个 NSPopUpButton
让用户选择货币列表,我怎样才能让 collapsed/closed 按钮只显示货币缩写而不是所选货币的菜单标题 (这是货币的全称)?
我想我可以重写子类(NSPopUpButtonCell
)中的绘制并自己绘制整个按钮,但我现在更喜欢重用系统外观的更轻量级的方法。
菜单项包含有关缩写的必要信息,因此这不是问题的一部分。
好的,所以我找到了如何修改标题。我创建了一个单元格 subclass ,我在其中覆盖了基于所选项目的标题设置。在我的例子中,我检查了问题中讨论的代表 object。
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 {}
}
}
然后在我的按钮 subclass 我设置单元格(我使用 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 中配置的单元格的所有属性。 我当然可以只设置单元格 class Interface Builder,这使它变得多余。
我还没有弄清楚的一件事 是我现在如何让按钮具有正确的固有内容大小。它仍然尝试与最长的常规标题一样宽。
我还没有弄清楚的第二件事 是如何使它与绑定一起工作。如果按钮内容是通过 Cocoa 绑定提供的,那么我只能绑定 contentValues,并且永远不会调用单元格的标题 属性。
子类 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)
}
以同样的方式,您可以在 NSPopUpButton
的子类中覆盖 intrinsicContentSize
。替换菜单,调用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
}