可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to capture keyevents in my little app.
What I have done:
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 } ... }
What happens:
When a key pressed, the Funk
sound effect plays.
I've seen many posts talking about how this is a delegate the belongs to NSView
and NSViewController
does not have access. But the keydown
function override
auto completes in a class of type NSViewController
leading me to believe that this is wrong.
回答1:
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") } } }
To get rid of the purr sound when pressing the character keys you need to subclass your view, override the method performKeyEquivalent and return true.
import Cocoa class View: NSView { override func performKeyEquivalent(with event: NSEvent) -> Bool { return true } }
Sample Project
回答2:
I was trying to find an answer for swift 3, here is what worked for me:
Swift 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 func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) } // Override the NSView keydown func to read keycode of pressed key override func keyDown(with theEvent: NSEvent) { Swift.print(theEvent.keyCode) return } }
回答3:
I manage to get it work from subclass of NSWindowController
class MyWindowController: NSWindowController { override func keyDown(theEvent: NSEvent) { print("keyCode is \(theEvent.keyCode)") } }
UPDATE:
import Cocoa protocol WindowControllerDelegate { func keyDown(aEvent: NSEvent) } class WindowController: NSWindowController { var delegate: WindowControllerDelegate? override func windowDidLoad() { super.windowDidLoad() delegate = window?.contentViewController as! ViewController } override func keyDown(theEvent: NSEvent) { delegate?.keyDown(theEvent) } }
and ViewController:
class ViewController: NSViewController, WindowControllerDelegate { @IBOutlet weak var textField: NSTextField! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override var representedObject: AnyObject? { didSet { // Update the view, if already loaded. } } override func keyDown(theEvent: NSEvent) { textField.stringValue = "key = " + (theEvent.charactersIgnoringModifiers ?? "") textField.stringValue += "\ncharacter = " + (theEvent.characters ?? "") textField.stringValue += "\nmodifier = " + theEvent.modifierFlags.rawValue.description } }
回答4:
Swift4
Just found a solution for the very same problem, Swift4. The idea behind that: if the pressed key was handled by a custom logic, the handler shall return nil, otherwise the (unhandled) event...
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 { switch Int( event.keyCode) { case kVK_Escape: // do what you want to do at "Escape" return true default: return false } } }
And here we are: no Purr / Funk sound when key is pressed...