Swift - 从NSViewController捕获keydown

Cri*_*pto 34 macos swift

我想在我的小应用程序中捕获关键事件.

我做了什么:

class ViewController : NSViewController {
...
  override func keyDown(theEvent: NSEvent) {
        if theEvent.keyCode == 124 {
            println("abc")
        } else {
            println("abcd")
        }
    }

    override var acceptsFirstResponder: Bool {
        return true
    }

    override func becomeFirstResponder() -> Bool {
        return true
    }

    override func resignFirstResponder() -> Bool {
        return true
    }

...
}
Run Code Online (Sandbox Code Playgroud)

怎么了:

按下某个键时,会播放Funk声音效果.

我看过很多帖子都在谈论这是一个属于哪个代表NSView,NSViewController也没有访问权限.但是keydown函数overrideauto在一类类型中完成,NSViewController导致我认为这是错误的.

Leo*_*bus 58

Xcode 8.2.1•Swift 3.0.2

import Cocoa

class ViewController: NSViewController {

    @IBOutlet var textField: NSTextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        NSEvent.addLocalMonitorForEvents(matching: .flagsChanged) {
            self.flagsChanged(with: $0)
            return $0
        }
        NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
            self.keyDown(with: $0)
            return $0
        }
    }
    override func keyDown(with event: NSEvent) {
        switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
        case [.command] where event.characters == "l",
             [.command, .shift] where event.characters == "l":
            print("command-l or command-shift-l")
        default:
            break
        }
        textField.stringValue = "key = " + (event.charactersIgnoringModifiers
            ?? "")
        textField.stringValue += "\ncharacter = " + (event.characters ?? "")
    }
    override func flagsChanged(with event: NSEvent) {
        switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
        case [.shift]:
            print("shift key is pressed")
        case [.control]:
            print("control key is pressed")
        case [.option] :
            print("option key is pressed")
        case [.command]:
            print("Command key is pressed")
        case [.control, .shift]:
            print("control-shift keys are pressed")
        case [.option, .shift]:
            print("option-shift keys are pressed")
        case [.command, .shift]:
            print("command-shift keys are pressed")
        case [.control, .option]:
            print("control-option keys are pressed")
        case [.control, .command]:
            print("control-command keys are pressed")
        case [.option, .command]:
            print("option-command keys are pressed")
        case [.shift, .control, .option]:
            print("shift-control-option keys are pressed")
        case [.shift, .control, .command]:
            print("shift-control-command keys are pressed")
        case [.control, .option, .command]:
            print("control-option-command keys are pressed")
        case [.shift, .command, .option]:
            print("shift-command-option keys are pressed")
        case [.shift, .control, .option, .command]:
            print("shift-control-option-command keys are pressed")
        default:
            print("no modifier keys are pressed")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要在按下字符键时摆脱呜呜声,需要对视图进行子类化,请覆盖方法performKeyEquivalent并返回true.

import Cocoa

class View: NSView {
    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

示例项目


Kri*_*gel 12

Swift4

刚刚找到了解决同样问题的解决方案,Swift4.这背后的想法:如果按下的键由自定义逻辑处理,处理程序将返回nil,否则(未处理的)事件...

class MyViewController: NSViewController {
   override func viewDidLoad() {
      super.viewDidLoad()
      // ...
      NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
         if self.myKeyDown(with: $0) {
            return nil
         } else {
            return $0
         }
      }
   }
   func myKeyDown(with event: NSEvent) -> Bool {
      // handle keyDown only if current window has focus, i.e. is keyWindow
      guard let locWindow = self.view.window,
         NSApplication.shared.keyWindow === locWindow else { return false }
      switch Int( event.keyCode) {
      case kVK_Escape:
         // do what you want to do at "Escape"
         return true
      default: 
         return false
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我们在这里:当按下按键时没有Purr/Funk声音......

[更新]添加了keyWindow的检查.如果没有这个,即使另一个视图/窗口包含第一个响应者,也会触发keyDown()...

  • 这是唯一帮助我摆脱to声的答案 (2认同)

Ake*_*ian 8

我试图找到swift 3的答案,这对我有用:

斯威夫特3

import Cocoa

// We subclass an NSView

class MainView: NSView {

    // Allow view to receive keypress (remove the purr sound)
    override var acceptsFirstResponder : Bool {
        return true
    }

    // Override the NSView keydown func to read keycode of pressed key
    override func keyDown(with theEvent: NSEvent) {
        Swift.print(theEvent.keyCode)
    }

}
Run Code Online (Sandbox Code Playgroud)