防止逃脱钥匙用一个封闭式盒子关闭NSPANEL



有人知道在钥匙窗口时阻止逃脱键关闭NSPanel的最佳方法吗?我的面板是一个子窗口,我希望它的行为更像窗口的半永久部分,更像是抽屉,对于其中的文本控件,我想拥有逃生键取消编辑。

我最近在可可文档中找到了有关Windows和逃生密钥的更多信息。在cancelOperation:下的NSResponder类参考中,其中说:"窗口将cancelOperation:的默认操作消息发送给第一响应者,从那里传播响应者链的消息"。NSPanel似乎有所不同,窗口关闭而没有第一响应者获取cancelOperation:呼叫或NSTEXTVIEW代表获得doCommandBySelector:呼叫。

我对In&考虑到我一直在做OS X的工作,OUT的响应链链条是可耻的。我以为我需要在NSPanel子类中制作keyDown:,就像普通窗口一样。我尝试覆盖NSPanel并可以捕获keyDown:,将呼叫转发到NSWindowkeyDown:而不是super,但没有变化,但逃脱仍然没有给第一响应者的消息关闭窗口。这是合理的尝试吗?

然后,我试图完全重新进化我的面板子类的keyDown:,使其这样做:

[self.firstResponder cancelOperation:self]

我认为这会让我的文本字段处理逃生通常的期望,也许如果没有文本字段是第一响应者,那么呼叫就会消失。但是,我尝试了它,面板就像以前一样关闭。显然,我不是在正确的级别拦截事情。

有人知道在低级别的钥匙按事件和面板关闭之间运行的方法序列,还是我需要覆盖的方法来拦截它并确保cancelOperation:转到我的第一响应者?

keith-knauber答案的快速港口:

class ValueEditor : NSObject, NSControlTextEditingDelegate {
enum CommandType {
    case none
    case accept
    case next
    case prev
    case cancel
}
class func commandTypeType(for command: Selector) -> CommandType {
    let commandType: CommandType
    switch command {
    case #selector(NSStandardKeyBindingResponding.insertLineBreak(_:)) :
        fallthrough
    case #selector(NSStandardKeyBindingResponding.insertNewline(_:)) :
        fallthrough
    case #selector(NSStandardKeyBindingResponding.insertNewlineIgnoringFieldEditor(_:)) :
        fallthrough
    case #selector(NSStandardKeyBindingResponding.insertParagraphSeparator(_:)) :
        commandType = .accept
    case #selector(NSStandardKeyBindingResponding.insertTab(_:)) :
        fallthrough
    case #selector(NSWindow.selectNextKeyView(_:)) :
        fallthrough
    case #selector(NSStandardKeyBindingResponding.insertTabIgnoringFieldEditor(_:)) :
        commandType = .next
    case #selector(NSStandardKeyBindingResponding.insertBacktab(_:)) :
        fallthrough
    case #selector(NSWindow.selectPreviousKeyView(_:)) :
        commandType = .prev
    case #selector(NSStandardKeyBindingResponding.cancelOperation(_:)) :
        commandType = .cancel
    default:
        commandType = .none
    }
    return commandType
}

// MARK: - NSControl delegate
func control(_ control: NSControl,
             textView: NSTextView,
             doCommandBy commandSelector: Selector) -> Bool {
    let commandType: CommandType = ValueEditor.commandTypeType(for: commandSelector)
    switch commandType {
    case .cancel:
        control.abortEditing()
        // When the user hits 'ESC' key with a field editor active, cancel the field editor,
        // but return `true` here so that the NSPanel doesn’t close.
        // Hitting 'ESC' a second time will close the NSPanel.
        return true
    default:
        return false
    }
}

}

不要忘记将Valueeditor实例设置为NstextView对象的代表!

在您的笔尖或代码中的某个地方,将您的NstableView委托设置为控制器。

请注意,setDelegate:与setDataSource不同:!

在我的情况下: @interface valueeditor:nsobject

  + (ValueEditorCmdType)cmdTypeForSelector:(SEL)command
  {
     ValueEditorCmdType cmdType = kCmdTypeNone;
     if ( command == @selector(insertLineBreak:) || command == @selector(insertNewline:) || command == @selector(insertNewlineIgnoringFieldEditor:) || command == @selector(insertParagraphSeparator:))
        cmdType = kCmdTypeAccept;
     else if (  command == @selector(insertTab:) || command == @selector(selectNextKeyView:)  || command == @selector(insertTabIgnoringFieldEditor:))
        cmdType = kCmdTypeNext;
     else if ( command == @selector(insertBacktab:) || command == @selector(selectPreviousKeyView:))
        cmdType = kCmdTypePrev;
     else if ( command == @selector(cancelOperation:) )   
        cmdType = kCmdTypeCancel;
     return cmdType;
  }
  #pragma mark - NSControl delegate
  - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
  {
     ValueEditorCmdType cmdType = [ValueEditor cmdTypeForSelector:command];
     if ( cmdType == kCmdTypeCancel )
     {
        [control abortEditing];  
        // when user hits 'ESC' key with a field editor active, cancel the field editor,
        // but return YES here so that NSPanel doesn't close.  
        // Hitting 'ESC' a 2nd time will close the NSPanel.
        return YES;
     }
     return NO;
  }

相关内容

  • 没有找到相关文章

最新更新