【发布时间】:2019-07-26 04:09:58
【问题描述】:
在 MacOS/Cocoa/Swift 4.2/Xcode 10.1 中,我试图创建一个 NSPanel,它作为一个轻量级标记调色板漂浮在我的文档窗口上,它与文档窗口中发生的(主要基于键盘的)编辑会话进行交互。
我在面板中主要有按钮控件,但是当用户单击它时,一个组合框值得关注。除此之外,我想避免成为关键窗口(避免捕获未来的关键事件并避免突出显示标题栏)当任何其他控件被按下时,或者当面板通过拖动重新定位时,或者面板点击时死角。在我看来,这与文档描述的行为完全一样,如果我的面板被标记为 becomeKeyOnlyIfNeeded,我应该具有的行为,但我无法让它工作。
在 Interface Builder 中,我将面板指定为(我自己的)子类 InspectorPanel,其样式为:常规面板、标题栏、阴影、关闭、可恢复和停用时隐藏设置(其他一切都清楚)。我在子类中指定了 becomeKeyOnlyIfNeeded:
class InspectorPanel : NSPanel {
override var becomesKeyOnlyIfNeeded: SwiftBool {
get {
return true
}
set {
}
}
}
(我也尝试在控制器的 awakeFromNib 中设置它,在控制器的窗口中设置为?NSPanel。)
此设置似乎没有明显效果。面板正确地浮动在文档窗口上方,但是当组合框成功地从文档窗口中获取关键焦点时,按 any 控件、单击面板空白区域或拖动面板标题栏也是如此,以及可能的其他操作。虽然我可以为每种情况编写处理程序,手动查找活动文档窗口并 makeKeyWindow(thatWindow) 将焦点传递回它所属的位置,但从检查器设计的角度来看,这似乎不优雅;强迫我写一些我目前不需要的处理程序(例如标题栏拖动);让我担心我错过的类似案例。
只有当我的单个组合框需要它时,是否有某种方法可以成功成为关键?如果有,怎么做?
其他努力:
我知道 needsPanelToBecomeKey 并且对其文档感到有些困惑。它表明,一旦我在面板上设置了 becomeKeyOnlyIfNeeded,NOTHING 将允许面板获取焦点,直到我在特定子视图(例如我的组合框)上启用 needsPanelToBecomeKey。事实上,由于设置 becomeKeyOnlyIfNeeded 对阻止窗口成为键没有任何影响,因此无论我是否在子视图上设置 comboBox.needsPanelToBecomeKey,我都看不出响应有什么不同。)
我也知道 rejectsFirstResponder,并尝试在面板中的各种控件(例如 NSButtons)上设置它,以查看这是否会阻止它们将焦点转移到窗口。不走运。)
如果我设置 canBecomeKeyWindow = false,那么我永远不会获得关键焦点,即使在我的组合框中也是如此。 (这似乎是合理且出乎意料的;我只是列出它是为了全面。)
许多其他应用程序似乎都有浮动窗口,其行为与我想要的一样,但我没有找到可以帮助我找到错误的源代码。你能帮忙吗?
【问题讨论】:
-
为什么是
SwiftBool?另外,在面板的样式掩码中包含.nonactivatingPanel是否有帮助? -
抱歉,SwiftBool 是 typealias SwiftBool=Swift.Bool 的类型别名。 (这是从同样导入了不同定义 Bool 的 Obj-C 框架的代码中复制的,因此两者的客户端代码必须通过命名空间来区分。) Re .nonactivatingPanel,正如我所读到的,这适用于您不想要的情况窗口点击激活app,而不仅仅是panel。但无论如何,在 IB 中设置 Non Activating 并不会阻止当我拖动窗口或单击其中的 anywhere 时窗口成为键(例如接收 becomeKey 通知、突出显示标题栏) (子视图与否)。