当在NSTextField中按下回车键时执行一个操作?

76

我现在有一个小问题。我想在NSTextField中按下回车键时执行一个方法。用户应该能够输入他的数据,并在按下回车键后立即执行一个计算方法。

8个回答

84

您可以通过设置文本字段的操作来实现此目的。在IB中,将文本字段的选择器连接到您的控制器或呈现所需使用的IBAction的任何对象。

要在代码中设置它,请向NSTextField发送setTarget:消息和setAction:消息。例如,如果您正在代码中为控制器对象设置此选项,并且您的textField outlet称为myTextField:

- (void)someAction:(id)sender
{
  // do something interesting when the user hits <enter> in the text field
}

// ...

[myTextField setTarget:self];
[myTextField setAction:@selector(someAction:)];

1
需要注意的是,这在IB中不起作用(至少我无法使其起作用)。 - StuFF mc
6
除非我离开该字段,否则它也会执行该操作。 - citelao
85
在现代XCode中,NSTextField可以具有不同的动作模式。默认情况下,NSTextField设置为“在结束编辑时发送”,这意味着无论何种原因(例如,切换到其他应用程序)停止编辑时都会发送操作。但是,您可以在Interface Builder中将其切换为“仅在按Enter键时发送”(在属性选项卡上,在“文本字段”属性组的底部),以使其仅在用户实际按下Enter键时发送操作。 - Trevor Powell
1
不幸的是,当你点击 NSSearchField 右侧出现的 X 时,它也会发送选择器。苹果的文档建议点击 X 就像删除所有内容并输入回车一样,因此调用了选择器,这样你就可以查找空的 NSSearchField 并清除结果。如果你不喜欢这种行为,我认为唯一的解决方法是添加类似以下代码的代码: [[[searchField cell] cancelButtonCell] setAction:@selector(clearSearchField:)]; [[[searchField cell] cancelButtonCell] setTarget:self]; - Winter Dragoness
这个答案不完整,因为它只处理了界面构建器的情况。请考虑下面 @Raff 的答案:它也处理了编程的情况。 - Sam Ballantyne
显示剩余3条评论

54

你只需要做这件事

对于一些键(如Enter、Delete、Backspace等)

self.textfield.delegate = self;

然后实现这个方法

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector
{
    NSLog(@"Selector method is (%@)", NSStringFromSelector( commandSelector ) );
    if (commandSelector == @selector(insertNewline:)) {
        //Do something against ENTER key

    } else if (commandSelector == @selector(deleteForward:)) {
        //Do something against DELETE key

    } else if (commandSelector == @selector(deleteBackward:)) {
        //Do something against BACKSPACE key

    } else if (commandSelector == @selector(insertTab:)) {
        //Do something against TAB key

    } else if (commandSelector == @selector(cancelOperation:)) {
        //Do something against Escape key
    }
    // return YES if the action was handled; otherwise NO
} 

3
另一个相关的命令是 cancelOperation:,它将由 Esc 键触发。 - Abhi Beckert

33

Swift 3 / 4 / 5版本@M.ShuaibImran的解决方案:

首先将您的ViewController子类化为:NSTextFieldDelegate

class MainViewController: NSViewController, NSTextFieldDelegate {
  ...
} 

在你的viewDidLoad()方法中将textField的代理分配给ViewController:

self.textField.delegate = self

包含处理键盘响应的NSTextFieldDelegate方法:

Include the NSTextFieldDelegate method that handles keyboard responders:
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
    if (commandSelector == #selector(NSResponder.insertNewline(_:))) {
        // Do something against ENTER key
        print("enter")
        return true
    } else if (commandSelector == #selector(NSResponder.deleteForward(_:))) {
        // Do something against DELETE key
        return true
    } else if (commandSelector == #selector(NSResponder.deleteBackward(_:))) {
        // Do something against BACKSPACE key
        return true
    } else if (commandSelector == #selector(NSResponder.insertTab(_:))) {
        // Do something against TAB key
        return true
    } else if (commandSelector == #selector(NSResponder.cancelOperation(_:))) {
        // Do something against ESCAPE key
        return true
    }
    
    // return true if the action was handled; otherwise false
    return false
}

1
谢谢这个。正是我在寻找的小东西,而且将近三年后它仍然可以在Swift 5/Xcode 11中运行,没有任何更改或Xcode建议。 - Aeger

26

在你的委托(NSTextFieldDelegate)中添加以下内容:

-(void)controlTextDidEndEditing:(NSNotification *)notification
{
    // See if it was due to a return
    if ( [[[notification userInfo] objectForKey:@"NSTextMovement"] intValue] == NSReturnTextMovement )
    {
        NSLog(@"Return was pressed!");
    }
}

2
这段代码是用于文本字段失去焦点的情况,而不是按下回车键。 - Gargo
不要忘记在.h文件和代码/IB中设置您的代理,并在IB中将文本字段操作修改为“仅在按Enter时发送”。 - nalply
2
@Gargo 这并不是真的,至少在El Capitan上不是。按下Enter键会收到这条消息。要么是某种验证引起的,要么是其他原因。 - Marek H

18

这很容易,您可以直接从UI编辑器中完成

  1. 右键单击文本字段,将动作引用拖到按钮上,如下图所示

enter image description here

  1. 现在会给您一些选项,如下图所示,您需要选择执行点击

enter image description here

  1. 现在应该是这样的

enter image description here

注意:只要您按下TabEnter键,事件就会被触发。如果您希望用户仅在按下Enter键时才触发操作,则必须进行设置。转到属性检查器并更改操作属性为仅在按Enter发送,如下图所示。

enter image description here


1
嗨,我做完这个后按回车键时,它会选择文本字段中的整个文本,如何停止这种情况? - souvickcse
@Vikas Bansal 谢谢,兄弟。你的解决方案对我起了作用。 - Bilal Basharat
@souvickcse 我遇到了完全相同的问题。你在这里找到任何解决方案了吗?虽然已经过去3.5年,但是...感谢互联网 :D - Aeger
说实话,我忘记了这个问题本身,请尝试其他解决方案,我认为你的问题会得到解决。 - souvickcse
是的...几天后,我找到了一个解决方案,可以在调用操作后突出显示文本:只需将这三行放在最后:let resultLength = String(result).count(如果要计数的项目已经是String,当然不需要转换为String),然后添加此行:yourNSTextField.currentEditor()?.selectedRange = NSRange(location: resultLength, length: 0),然后再添加这一行:yourNSTextField.displayIfNeeded()光标将跳到您呈现内容的最后一个字符后面。 - Aeger
感谢分享“仅在按下回车键时发送”的操作! - LinusGeffarth

4

NSTextFieldDelegatecontrol:textView:doCommandBySelector:是你的好朋友。

寻找insertNewline:命令。


谢谢这个。虽然我没有用它(我在顶部使用了setAction:),但我发现了很多有用的地方,其中包括insertNewline: - StuFF mc

1
在Interface Builder中,单击您的NSTextField,转到连接编辑器,从选择器拖动到您的控制器对象 - 您的操作应该出现!

1

最佳实践是将 NSTextField 的值与 NSString 属性绑定。

例如,定义一个方法:

(void)setTextFieldString:(NSString *)addressString {}

添加绑定:
[textField bind:@"value" toObject:self withKeyPath:@"self.textFieldString" options:nil];

输入任何文本并按回车键,将调用setTextFieldString


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接