Swift: 如何更改 NSPopupButton 编辑菜单项文本
Swift: How to change NSPopupButton edit menu item text
我的 GUI 上有一个 NSPopupButton,我正在寻找一种方法来以编程方式更改特定项目的文本:
'item 1'
'item 2' ---> 'item b'
'item 3'
您问题的直接答案是,您可以通过 NSPopUpButton
的 menu
属性 访问这些项目,然后是 items
属性在出现的菜单上。但是请不要在这里停止阅读,因为我不会那样做。
您想要更改菜单项的原因很可能是为了反映模型中某物的状态。也许标题是 context-sensitive 并且应该根据当前选择或类似的东西而改变。您通常可以在根本不需要 NSPopUpButton
的出口的情况下执行此操作,只需在菜单项目标的 validateMenuItem
方法中执行即可:
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
if menuItem.action == #selector(someAction:) {
if self.someCondition {
menuItem.title = "Foo"
} else {
menuItem.title = "Bar"
}
}
return super.validateMenuItem(menuItem)
}
这不仅可以简化您的设计并降低程序逻辑需要了解您的 UI 设置的程度,而且更加灵活,因为它适用于任何菜单项指向相同的目标和行动。如果您决定将菜单项移出 pop-up 按钮并移至标准菜单栏、toolbar-based 菜单或其他内容,或者如果您希望在其中几个位置有多个菜单项, 它们的工作方式完全相同,您无需编写任何新代码。
我有时使用的另一个技巧是通过 Cocoa 绑定填充菜单项的标题。这也具有将 UI 与界面分离的效果,但它是一个您可能还不想跳入的主题的更高级的部分。
编辑:既然我知道了你的用例,那正是我倾向于使用 Cocoa 绑定的那种东西 :-) 比如:
class MyViewController: NSViewController {
...
// make these @objc and dynamic so that they are KVC-compliant
@objc dynamic var password: String
@objc dynamic var bits: Int
// register our password strength as dependent on 'password' and 'bits'
@objc private static let keyPathsForValuesAffectingPasswordStrength: Set<String> = [
#keyPath(password),
#keyPath(bits)
]
@objc var passwordStrength: String {
// obviously you'll do a better test than this in real life ;-)
if self.password.count >= 8 {
return NSLocalizedString("Strong", comment: "Strong")
} else {
return NSLocalizedString("Weak", comment: "Weak")
}
}
...
}
基本上,这里发生的事情是:
一切都是@objc
因为CocoaBindings是用Objective-C写的,需要能够看到我们的属性
将 dynamic
添加到 password
和 bits
属性允许 Cocoa 将魔法粘贴到访问器中,使它们在属性时触发通知改变。
keyPathsForValuesAffectingPasswordStrength
属性 告诉 Cocoa 当为 password
或 bits
触发通知时,它们也应该触发passwordStrength
.
现在,我们只需转到 Interface Builder,并将我们的安全密码字段绑定到 password
属性,如下所示:
然后,我们将滑块绑定到 bits
属性,如下所示:
对于我们的标签,我们变得更奇特一些,并设置了一个包含 passwordStrength
和 bits
的模式:
因此,除了一些 属性 定义外,几乎没有任何代码,我们得到:
很漂亮,嗯?
我的 GUI 上有一个 NSPopupButton,我正在寻找一种方法来以编程方式更改特定项目的文本:
'item 1'
'item 2' ---> 'item b'
'item 3'
您问题的直接答案是,您可以通过 NSPopUpButton
的 menu
属性 访问这些项目,然后是 items
属性在出现的菜单上。但是请不要在这里停止阅读,因为我不会那样做。
您想要更改菜单项的原因很可能是为了反映模型中某物的状态。也许标题是 context-sensitive 并且应该根据当前选择或类似的东西而改变。您通常可以在根本不需要 NSPopUpButton
的出口的情况下执行此操作,只需在菜单项目标的 validateMenuItem
方法中执行即可:
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
if menuItem.action == #selector(someAction:) {
if self.someCondition {
menuItem.title = "Foo"
} else {
menuItem.title = "Bar"
}
}
return super.validateMenuItem(menuItem)
}
这不仅可以简化您的设计并降低程序逻辑需要了解您的 UI 设置的程度,而且更加灵活,因为它适用于任何菜单项指向相同的目标和行动。如果您决定将菜单项移出 pop-up 按钮并移至标准菜单栏、toolbar-based 菜单或其他内容,或者如果您希望在其中几个位置有多个菜单项, 它们的工作方式完全相同,您无需编写任何新代码。
我有时使用的另一个技巧是通过 Cocoa 绑定填充菜单项的标题。这也具有将 UI 与界面分离的效果,但它是一个您可能还不想跳入的主题的更高级的部分。
编辑:既然我知道了你的用例,那正是我倾向于使用 Cocoa 绑定的那种东西 :-) 比如:
class MyViewController: NSViewController {
...
// make these @objc and dynamic so that they are KVC-compliant
@objc dynamic var password: String
@objc dynamic var bits: Int
// register our password strength as dependent on 'password' and 'bits'
@objc private static let keyPathsForValuesAffectingPasswordStrength: Set<String> = [
#keyPath(password),
#keyPath(bits)
]
@objc var passwordStrength: String {
// obviously you'll do a better test than this in real life ;-)
if self.password.count >= 8 {
return NSLocalizedString("Strong", comment: "Strong")
} else {
return NSLocalizedString("Weak", comment: "Weak")
}
}
...
}
基本上,这里发生的事情是:
一切都是
@objc
因为CocoaBindings是用Objective-C写的,需要能够看到我们的属性将
dynamic
添加到password
和bits
属性允许 Cocoa 将魔法粘贴到访问器中,使它们在属性时触发通知改变。keyPathsForValuesAffectingPasswordStrength
属性 告诉 Cocoa 当为password
或bits
触发通知时,它们也应该触发passwordStrength
.
现在,我们只需转到 Interface Builder,并将我们的安全密码字段绑定到 password
属性,如下所示:
然后,我们将滑块绑定到 bits
属性,如下所示:
对于我们的标签,我们变得更奇特一些,并设置了一个包含 passwordStrength
和 bits
的模式:
因此,除了一些 属性 定义外,几乎没有任何代码,我们得到:
很漂亮,嗯?