有人知道防止转义键在关键窗口时关闭NSPanel
的最佳方法吗?我的面板是一个子窗口,我希望它表现得更像窗口的半永久性部分,更像是抽屉,对于其中的文本控件,我想让Escape键取消编辑。
我最近在Cocoa文档中发现了更多关于windows和Escape键的内容。在cancelOperation:
下的NSResponder类引用中,它表示“窗口向第一响应者发送cancelOperation:
的默认操作消息,然后消息从响应者链向上传播”。 NSPanel
似乎有所不同,窗口关闭时第一个响应者没有cancelOperation:
来电或NSTextView代表获得doCommandBySelector:
来电。
我对in&的了解考虑到我一直在做OS X的工作,我认为响应者链是可耻的。我想我需要在我的keyDown:
子类中使NSPanel
的行为与普通窗口的行为相同。我尝试覆盖NSPanel
并抓住keyDown:
,将来电转发至NSWindow
的{{1}}代替keyDown:
,但没有变化,Escape仍然关闭窗口,没有消息给第一响应者。尝试是否合理?
然后我尝试完全重新实现我的面板子类'super
,使其成功:
keyDown:
我认为这会让我的文本字段处理它通常所期望的转义,并且如果没有文本字段是第一响应者那么该调用将会死路一条。但是,我尝试了它,面板就像以前一样关闭。显然,我并没有在适当的层面拦截事物。
有没有人知道在低级别按键事件和面板关闭之间运行的方法序列,或者我需要覆盖哪些方法来拦截它并确保[self.firstResponder cancelOperation:self]
转到我的第一响应者?< / p>
答案 0 :(得分:0)
在您的笔尖或代码中的某处,将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;
}
答案 1 :(得分:0)
基思·库纳(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对象的委托!