MacOS:如何让 NSPanel 抵抗关键焦点(使用 becomesKeyOnlyIfNeeded?)
MacOS: how to get NSPanel to resist key focus (with becomesKeyOnlyIfNeeded?)
在 MacOS/Cocoa/Swift 4.2/Xcode 10.1 中,我正在尝试创建一个 NSPanel,它漂浮在我的文档 window 上,作为与(主要是 keyboard-based) 编辑 session 发生在文档 window.
中
我在面板中主要有按钮控件,但有一个 combo-box 在用户单击时值得关注。除此之外,我想避免成为关键 window (避免捕获未来的关键事件并避免突出显示标题栏)当任何其他控件被按下时,或者当面板通过拖动或在panel-clicks 死 space。如果我的面板被标记为 becomeKeyOnlyIfNeeded,这听起来与文档描述的行为完全一样,但我无法让它工作。
在 Interface Builder 中,我将我的面板指定为(我自己的)子类 InspectorPanel,样式为:常规面板、标题栏、阴影、关闭、可恢复和停用时隐藏设置(其他一切都清楚)。我在子类中指定 becomesKeyOnlyIfNeeded:
class InspectorPanel : NSPanel {
override var becomesKeyOnlyIfNeeded: SwiftBool {
get {
return true
}
set {
}
}
}
(我也尝试过在控制器的 awakeFromNib 中设置它,在控制器的 window as?NSPanel 上。)
这个设置好像没有什么明显的效果。面板正确地漂浮在文档 window 上方,但是当组合框成功地将关键焦点从文档 window 上移开时,按下 any 控件或单击在面板白色 space 中,或拖动面板标题栏,以及可能的其他操作。虽然我可以为这些案例中的每一个编写处理程序,手动找到活动文档 window 和 makeKeyWindow(thatWindow) 以将焦点传递回它所属的位置,但从检查器设计的角度来看,这似乎不够优雅;迫使我在目前需要 none 的地方编写一些处理程序(例如 title-bar 拖动);让我担心我错过了类似的案例。
是否有一些方法可以仅在我的单个组合框需要时才成功成为键?如果可以,怎么做?
其他努力:
我知道 needsPanelToBecomeKey 并且对其文档有些困惑。它表明,一旦我在面板上设置了 becomesKeyOnlyIfNeeded,在我对特定子视图(例如我的组合框)启用 needsPanelToBecomeKey 之前,NOTHING 将允许面板获取焦点。事实上,由于设置 becomesKeyOnlyIfNeeded 对阻止 window 成为关键没有影响,所以无论我是否在子视图上设置 comboBox.needsPanelToBecomeKey,我都看不出响应有什么不同。)
我也知道 refusesFirstResponder,并尝试在面板中的各种控件(例如 NSButtons)上设置它,看看这是否会阻止它们将关键焦点转移到 window .运气不好。)
如果我设置 canBecomeKeyWindow = false,那么我永远不会获得关键焦点,即使在我的组合框中也是如此。 (这似乎是有道理的,也是出乎意料的,我只是罗列一下。)
许多其他应用程序似乎有浮动 windows,它们的行为符合我的要求,但我找不到可以帮助我发现错误的源代码。你能帮忙吗?
在以编程方式创建 NSPanel
(NSWindow
的子类)时使用 NSWindowStyleMaskUtilityWindow
样式掩码,或者在 IB 中指定 "Utility Panel" 样式。
此样式定义了浮动调色板的外观和行为window。
我找到了问题的原因。显然我不明白我用来覆盖上面的 becomesKeyOnlyIfNeeded 的 Swift 初始值设定项的含义(尽管我对其他地方的其他属性成功使用了相同的语法!)。如果我删除了将 becomesKeyOnlyIfNeeded 定义为 always true 的尝试,而是沿着 window 初始化路径将其(继承的 属性)动态设置为 true,则面板的行为完全符合我的要求,除了"if needed"(在组合框中单击时)之外,抵抗键焦点。
换句话说,
class InspectorPanel : NSPanel {
override func awakeFromNib() {
super.awakeFromNib()
becomesKeyOnlyIfNeeded = true // REPLACES THE BELOW
}
/* REPLACED BY ABOVE
override var becomesKeyOnlyIfNeeded: SwiftBool {
get {
return true
}
set {
}
}
*/
}
完美运行。如果有人了解我的(已注释掉的)初始化程序做错了什么,我将不胜感激,但通过这种解决方法,我可以关闭有关面板行为的未决问题。
在 MacOS/Cocoa/Swift 4.2/Xcode 10.1 中,我正在尝试创建一个 NSPanel,它漂浮在我的文档 window 上,作为与(主要是 keyboard-based) 编辑 session 发生在文档 window.
中我在面板中主要有按钮控件,但有一个 combo-box 在用户单击时值得关注。除此之外,我想避免成为关键 window (避免捕获未来的关键事件并避免突出显示标题栏)当任何其他控件被按下时,或者当面板通过拖动或在panel-clicks 死 space。如果我的面板被标记为 becomeKeyOnlyIfNeeded,这听起来与文档描述的行为完全一样,但我无法让它工作。
在 Interface Builder 中,我将我的面板指定为(我自己的)子类 InspectorPanel,样式为:常规面板、标题栏、阴影、关闭、可恢复和停用时隐藏设置(其他一切都清楚)。我在子类中指定 becomesKeyOnlyIfNeeded:
class InspectorPanel : NSPanel {
override var becomesKeyOnlyIfNeeded: SwiftBool {
get {
return true
}
set {
}
}
}
(我也尝试过在控制器的 awakeFromNib 中设置它,在控制器的 window as?NSPanel 上。)
这个设置好像没有什么明显的效果。面板正确地漂浮在文档 window 上方,但是当组合框成功地将关键焦点从文档 window 上移开时,按下 any 控件或单击在面板白色 space 中,或拖动面板标题栏,以及可能的其他操作。虽然我可以为这些案例中的每一个编写处理程序,手动找到活动文档 window 和 makeKeyWindow(thatWindow) 以将焦点传递回它所属的位置,但从检查器设计的角度来看,这似乎不够优雅;迫使我在目前需要 none 的地方编写一些处理程序(例如 title-bar 拖动);让我担心我错过了类似的案例。
是否有一些方法可以仅在我的单个组合框需要时才成功成为键?如果可以,怎么做?
其他努力:
我知道 needsPanelToBecomeKey 并且对其文档有些困惑。它表明,一旦我在面板上设置了 becomesKeyOnlyIfNeeded,在我对特定子视图(例如我的组合框)启用 needsPanelToBecomeKey 之前,NOTHING 将允许面板获取焦点。事实上,由于设置 becomesKeyOnlyIfNeeded 对阻止 window 成为关键没有影响,所以无论我是否在子视图上设置 comboBox.needsPanelToBecomeKey,我都看不出响应有什么不同。)
我也知道 refusesFirstResponder,并尝试在面板中的各种控件(例如 NSButtons)上设置它,看看这是否会阻止它们将关键焦点转移到 window .运气不好。)
如果我设置 canBecomeKeyWindow = false,那么我永远不会获得关键焦点,即使在我的组合框中也是如此。 (这似乎是有道理的,也是出乎意料的,我只是罗列一下。)
许多其他应用程序似乎有浮动 windows,它们的行为符合我的要求,但我找不到可以帮助我发现错误的源代码。你能帮忙吗?
在以编程方式创建 NSPanel
(NSWindow
的子类)时使用 NSWindowStyleMaskUtilityWindow
样式掩码,或者在 IB 中指定 "Utility Panel" 样式。
此样式定义了浮动调色板的外观和行为window。
我找到了问题的原因。显然我不明白我用来覆盖上面的 becomesKeyOnlyIfNeeded 的 Swift 初始值设定项的含义(尽管我对其他地方的其他属性成功使用了相同的语法!)。如果我删除了将 becomesKeyOnlyIfNeeded 定义为 always true 的尝试,而是沿着 window 初始化路径将其(继承的 属性)动态设置为 true,则面板的行为完全符合我的要求,除了"if needed"(在组合框中单击时)之外,抵抗键焦点。
换句话说,
class InspectorPanel : NSPanel {
override func awakeFromNib() {
super.awakeFromNib()
becomesKeyOnlyIfNeeded = true // REPLACES THE BELOW
}
/* REPLACED BY ABOVE
override var becomesKeyOnlyIfNeeded: SwiftBool {
get {
return true
}
set {
}
}
*/
}
完美运行。如果有人了解我的(已注释掉的)初始化程序做错了什么,我将不胜感激,但通过这种解决方法,我可以关闭有关面板行为的未决问题。