MacOS:如何使NSPanel抵制关键焦点(使用getsKeyOnlyIfNeeded?)

时间:2019-03-04 19:19:48

标签: swift macos cocoa nspanel

在MacOS / Cocoa / Swift 4.2 / Xcode 10.1中,我试图创建一个NSPanel,它作为轻量级的标记调色板浮动在我的文档窗口上,该调色板与文档窗口中发生的(主要是基于键盘的)编辑会话进行交互。

我在面板中主要使用按钮控件,但是当用户单击时,一个组合框值得关注。除此之外,我想避免在按下任何其他控件时,通过拖动或在面板上单击鼠标来重新定位面板时,避免成为键窗口(避免同时捕获将来的键事件并避免突出显示标题栏)。死角。在我看来,这听起来像是文档描述的那样,即如果我的面板被标记为“ beforeKeyOnlyIfNeeded”,我应该具有的行为,但是我无法使其正常工作。

在Interface Builder中,我将面板指定为(我自己的)InspectorPanel子类,其样式为:常规面板,标题栏,阴影,关闭,可还原以及“停用时隐藏”设置(所有其他内容均清除)。我在子类中指定getsKeyOnlyIfNeeded:

class InspectorPanel : NSPanel {
     override var becomesKeyOnlyIfNeeded: SwiftBool {
        get {
            return true
        }
        set {
        }
    }    
}

(我也尝试过在控制器窗口的awakeFromNib中将其设置为NSPanel。)

此设置似乎没有可见效果。面板正确地浮动在文档窗口上方,但是当组合框成功将关键焦点移到文档窗口之外时,按 any 控件,单击面板空白或拖动面板标题栏也是如此,以及其他可能的操作。虽然我可以为每种情况编写处理程序,以手动找到活动文档窗口和makeKeyWindow(thatWindow)以将焦点传递回它所属的位置,但从检查器设计的角度来看,这似乎并不明智。强迫我写一些我现在不需要的处理程序(例如标题栏拖动);让我担心我想念的类似情况。

只有当我的单个组合框需要它时,是否有某种方法可以成功地成为关键?如果可以,怎么办?

其他努力:

  1. 我知道needsPanelToBecomeKey并对其文档有些困惑。这表明一旦我在面板上设置了成为KeyOnlyIfNeeded,NOTHING将允许面板抓取焦点,直到我在特定子视图(例如,我的组合框)上启用了needsPanelToBecomeKey为止。实际上,由于设置beginsKeyOnlyIfNeeded对阻止窗口变为关键没有影响,因此无论在子视图上是否设置comboBox.needsPanelToBecomeKey,我的响应都没有差别。)

  2. 我也知道了rejectsFirstResponder,并尝试在面板的各种控件(例如NSButtons)上进行设置,以查看是否阻止它们将键焦点转移到窗口上。没有运气。)

  3. 如果我将canBecomeKeyWindow设置为false,那么即使在我的comboBox中,也永远不会获得关键焦点。 (这似乎是合理且出乎意料的;我只是将其列出来以全面。)

很多其他应用程序似乎都具有浮动窗口,它们的行为与我想要的一样,但是我没有找到可以帮助我发现错误的源代码。你能帮忙吗?

2 个答案:

答案 0 :(得分:0)

以编程方式创建NSWindowStyleMaskUtilityWindowNSPanel的子类)时,可以使用NSWindow样式蒙版,也可以在IB中指定“实用程序面板”样式。

此样式定义了浮动调色板窗口的外观和行为。

答案 1 :(得分:0)

我发现了问题的原因。显然,我不理解我用来覆盖上面的遍及变成keysKeyOnlyIfNeeded的Swift初始化方法的含义(尽管我对其他位置的其他属性成功使用了相同的语法!)。如果我取消尝试将getsKeyOnlyIfNeeded定义为 always true,而是沿窗口初始化的路径动态将其(继承的属性)设置为true,则面板的行为与我想要的完全一样,除了不会聚焦键外,好吧,“如果需要”(在组合框中单击时)。

换句话说,

class InspectorPanel : NSPanel {

  override func awakeFromNib() {
    super.awakeFromNib()
    becomesKeyOnlyIfNeeded = true // REPLACES THE BELOW
  }

  /* REPLACED BY ABOVE
  override var becomesKeyOnlyIfNeeded: SwiftBool {
    get {
        return true
    }
    set {

    }
  }
  */
}

完美运行。如果有人知道我对(注释掉的)初始化程序做错了什么,我将不胜感激,但是有了这种解决方法,我可以解决有关面板行为的未解决问题。