关于 NSTextField 的keyDown事件
最近做MacOS开发, 有一个输入用户名的文本框,它是 NSTextField控件.
我想在按键按下的时候判断数输入的文本,如果出现非数字就拒绝输入到文本
也许有可以只输入数字的文本框,但是我这里是为了处理更复杂的逻辑;
如果你知道更好的办法,请告诉我,谢谢!
然而通过寻找,NSTextField 并没有keyDown事件;
我在 NSTextField 的NSTextFieldDelegate 中只有一个方法是关于文本改变的
//NSTextFieldDelegate
- (void)controlTextDidChange:(NSNotification *)obj
但是这个方法是在文本添加之后触发的,也就是说此方法调用的时候文本框中已经把那个不想要的字符输入到了文本框中.
当我重写 NSTextField 时,发现只有keyUp事件会触发;
从NSTextField到NSResponder的继承关系为:
NSTextField -> NSControl -> NSView -> NSResponder
NSResponder中有keyDown事件,但是在NSTextField并不会触发, 我猜测是在NSControl 这一层被拦截了.
经过各种头文件分析, 我变相的解决了keyDown的问题;
我发现NSTextField 的 currentEditor返回的是 NSText ,
而 NSTextView 是继承自 NSText 的,所以我猜想 NSTextField 的内部其实是包装了一个NSTextView,
因为NSTextView中提供了相对较全的键盘和内容改变事件,那么我可以给 currentEditor 的返回值(也就是NSText)设置一个delegate 然后直接处理底层事件;
首先让我要处理类似于keyDown事件的类实现NSTextViewDelegate
@interface LoginWindow: NSObject<NSTextViewDelegate>
在NSTextField成为第一响应者之后把currentEditor的返回值(也就是NSText)的delegate设置成这个类
//UITextField *m_textBox
[m_textBox becomeFirstResponder];
//[m_textBox setNeedsDisplay:YES];//我的控件是通过代码添加到的,所以我有这句
[m_textBox.currentEditor.delegate = self];
让后实现 NSTextViewDelegate 中的
//文本改变事件//方法名字太长了,我一般会在自己的代码中对参数进行换行
- (BOOL)textView:(NSTextView *)textView
shouldChangeTextInRanges:(NSArray<NSValue *> *)affectedRanges
replacementStrings:(nullable NSArray<NSString *> *)replacementStrings;
/////
我把它称作变相 NSTextField 的变相keyDown事件
这个方法我之前在做富文本的时候用过, 此方法会在文本填充到文本框之前调用;
也就是说我们在这个方法中调用
NSString *str = m_textBox.stringValue;
拿到的是上一次保存的文本;
然后我做在变相keyDown中的写法是:
- (BOOL)textView:(NSTextView *)textView //
shouldChangeTextInRanges:(NSArray<NSValue *> *)affectedRanges //
replacementStrings:(nullable NSArray<NSString *> *)replacementStrings
{
//textView 正在编辑的文本视图
//affectedRanges 受影响的范围
//replacementStrings 键盘输入的文本,或粘贴的文本 ,但是未进入文本框的文本
NSString *str = replacementStrings[0];
int len = (int)[str length];
if(len == 1)
{
//键盘输入
//处理...
}
else
{
//粘贴的项目
//处理...
}
//如果这个输入的字符是合法的 return YES;
//否则return NO;
//return NO 的话刚才输入或粘贴的文本将不会被添加到文本框
//我们可以改变replacementStrings里面的值影响添加到文本框中的类容
return NO;
}