NSTextField - 按下各个键时的通知

时间:2013-12-01 05:17:38

标签: macos cocoa

我正在创建一个应用程序,当用户输入NSTextField时,它会为按键添加声音。我需要捕获击键并知道每个按键的内容(如“d”或“space”或“6”)。该应用程序取决于此。没有别的办法了。

每个窗口都是NSDocument文件所有者,其中只有一个NSTextField,这是解析文档数据的位置,用户将键入。

经过几个小时的解析互联网寻求答案和破解代码后,最常见的四个答案是:

  1. “这不是事情的运作方式,这里是(无关的答案)”
  2. “你是Cocoa的新手,这是一个坏主意,使用control:textView:doCommandSelector:”并没有给我个人钥匙,而且有些钥匙需要他们自己独特的声音触发器。
  3. “使用controlTextDidChange:textView:shouldChangeTextInRange:replaceString:”controlTextDidChange不会为我提供单独的密钥,第二个仅适用于textViews或UIKit。
  4. 人们感到困惑,并回答了UIKit而不是AppKit的建议,这只是iOS版本。
  5. 奇怪的是,如果我继承NSTextField,它会收到-keyUp。我不知道-keyDown的去向。

    所以我的最终问题是:你能告诉我一些实际捕获发送到NSTextField的keyDown的逐步方法吗?即使它是一个黑客。即使这是一个可怕的想法。

    我很乐意解决这个问题!我非常感谢你的阅读。

4 个答案:

答案 0 :(得分:3)

controlTextDidChange 是一个很好的解决方案,但不要忘记这两件重要的事情:

  1. 将textField的委托绑定设置为您定义controlTextDidChange方法的对象。通常,在基于文档的应用程序中,它是窗口控制器,否则是您的应用程序委托。
  2. enter image description here

    1. 将textField的控件设置为" continuous"在属性检查器部分
    2. enter image description here

      如果你错过了那些积分,你就没有结果。

答案 1 :(得分:0)

如果您打印nslog,请尝试这样做,您将获得单个字符记录,例如按下“A”,您将在控制台中获得相同的内容: -

-(void)controlTextDidChange:(NSNotification*)obj
{
NSLog(@"%@",[yourTextfield stringValue]);

}

另外,不确定这只是你的要求。

答案 2 :(得分:0)

NSTextField的文本编辑由窗口提供的NSTextView处理,称为字段编辑器。请参阅NSWindow方法fieldEditor:forObject:NSWindowDelegate方法windowWillReturnFieldEditor:toObject:。我想你可以使用其中一个提供你自己的子类NSTextView作为字段编辑器。或者,您可以简单地使用NSTextView代替NSTextField吗?

答案 3 :(得分:0)

这是一个非常古老的问题,但是当我尝试实现一个可以对keyDown作出反应的NSTextField以便我可以创建一个热键首选项控件时,我发现我想要这个问题的答案。

不幸的是,这是一个非常非标准的用途,我找不到任何有直接答案的地方,但是我已经找到了一些在挖掘文档后工作的东西(尽管在Swift 4中)并且我想要将其发布在此处,以防其他人使用非标准用例。

这很大程度上取决于从Cocoa Text Architecture Guide

收集的信息

我的解决方案有三个组成部分:

  1. NSWindowController上创建NSWindowDelegate并设置NSWindow

    guard let windowController = storyboard.instanciateController(withIdentifier:NSStoryboard.SceneIdentifier("SomeSceneIdentifier")) as? NSWindowController else {
        fatalError("Error creating window controller");
    }
    if let viewController = windowController.contentViewController as? MyViewController {
        windowController.window?.delegate=viewController;
    }
    
  2. 您的NSWindowDelegate

    class MyViewController: NSViewController, NSWindowDelegate {
        // The TextField you want to capture keyDown on
        var hotKeyTextField:NSTextField!;
        // Your custom TextView which will handle keyDown
        var hotKeySelectionFieldEditor:HotKeySelectionTextView = HotKeySelectionTextView();
    
        func windowWillReturnFieldEditor(_ sender: NSWindow, to client: Any?) -> Any? {
            // If the client (NSTextField) requesting the field editor is the one you want to capture key events on, return the custom field editor. Otherwise, return nil and get the default field editor.
            if let textField = client as? NSTextField, textField.identifier == hotKeyTextField.identifier {
                return hotKeySelectionFieldEditor;
            }
            return nil;
        }
    }
    
  3. 您处理keyDown

    的自定义TextView
    class HotKeySelectionTextView: NSTextView {
        public override func keyDown(with event: NSEvent) {
            // Here you can capture the key presses and perhaps save state or communicate back to the ViewController with a delegate pattern if you prefer.
        }
    }
    
  4. 我完全承认这在某种程度上感觉像是一种解决方法,但是当我正在尝试使用Swift并且没有完全掌握所有最佳实践时,我无法对“Swift”做出权威主张-i-ness“这个解决方案,只是它允许NSTextField间接捕获keyDown事件,同时保持NSTextField的其余功能。