在Cocoa OSX中捕获双击

在Cocoa OSX中捕获双击,cocoa,macos,double-click,nsresponder,Cocoa,Macos,Double Click,Nsresponder,NSResponder似乎没有鼠标双击事件。有没有一个简单的方法来捕捉双击 方法mouseDown:和mouseUp:将NSEvent对象作为参数,包含有关单击的信息,包括clickCount应用程序通常在-[mouseUp:]上查看clickCount==2来确定双击 一种改进方法是跟踪鼠标在-[mouseDown:]上单击的位置,并查看鼠标向上位置上的增量是否很小(x和y方向上的增量均小于等于5点)。为鼠标向下:和鼠标向下:生成的NSEvent具有一个名为clickCount的属性。检查是否

NSResponder似乎没有鼠标双击事件。有没有一个简单的方法来捕捉双击

方法
mouseDown:
mouseUp:
将NSEvent对象作为参数,包含有关单击的信息,包括
clickCount

应用程序通常在-[mouseUp:]上查看clickCount==2来确定双击


一种改进方法是跟踪鼠标在-[mouseDown:]上单击的位置,并查看鼠标向上位置上的增量是否很小(x和y方向上的增量均小于等于5点)。

鼠标向下:
鼠标向下:
生成的
NSEvent
具有一个名为
clickCount
的属性。检查是否为2,以确定是否发生双击

示例实现:

- (void)mouseDown:(NSEvent *)event {
    if (event.clickCount == 2) {
        NSLog(@"Double click!");
    }
}

只需将其放在
NSResponder
(例如
NSView
)子类中即可。

普通
clickCount
解决方案的问题是,双击被认为只是两次单击。我的意思是,你仍然可以点击一下。如果你想对那一次点击做出不同的反应,你需要在点击计数的基础上再加上一些东西。以下是我(在Swift中)得到的结果:


就我个人而言,我检查了双击鼠标的功能:

- (void)mouseUp:(NSEvent *)theEvent
{

    if ([theEvent clickCount] == 2)
    {

        CGPoint point = [theEvent locationInWindow];
        NSLog(@"Double click on: %f, %f", point.x, point.y);

     }

}

我实现了一些类似于@jayarjo的东西,除了它有点模块化,您可以将它用于任何NSView或其子类。这是一个自定义手势识别器,可识别单击和双击动作,但在双击阈值超过之前不能识别单击:

//
//  DoubleClickGestureRecognizer.swift
//

import Foundation
/// gesture recognizer to detect two clicks and one click without having a massive delay or having to implement all this annoying `requireFailureOf` boilerplate code
final class DoubleClickGestureRecognizer: NSClickGestureRecognizer {

    private let _action: Selector
    private let _doubleAction: Selector
    private var _clickCount: Int = 0

    override var action: Selector? {
        get {
            return nil /// prevent base class from performing any actions
        } set {
            if newValue != nil { // if they are trying to assign an actual action
                fatalError("Only use init(target:action:doubleAction) for assigning actions")
            }
        }
    }

    required init(target: AnyObject, action: Selector, doubleAction: Selector) {
        _action = action
        _doubleAction = doubleAction
        super.init(target: target, action: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(target:action:doubleAction) is only support atm")
    }

    override func mouseDown(with event: NSEvent) {
        super.mouseDown(with: event)
        _clickCount += 1
        let delayThreshold = 0.15 // fine tune this as needed
        perform(#selector(_resetAndPerformActionIfNecessary), with: nil, afterDelay: delayThreshold)        
        if _clickCount == 2 {
            _ = target?.perform(_doubleAction)
        }
    }

    @objc private func _resetAndPerformActionIfNecessary() {
        if _clickCount == 1 {
            _ = target?.perform(_action)
        }
        _clickCount = 0
    }
}
用法:

let gesture = DoubleClickGestureRecognizer(target: self, action: #selector(mySingleAction), doubleAction: #selector(myDoubleAction))
button.addGestureRecognizer(gesture)

@objc func mySingleAction() {
 //  ... single click handling code here
}

@objc func myDoubleAction() {
 // ... double click handling code here
 }

我更喜欢的
mouseDown:
+
NSTimer
方法是
nsclickesturerecognizer

    let doubleClickGestureRecognizer = NSClickGestureRecognizer(target: self, action: #selector(self.myCustomMethod))
    doubleClickGestureRecognizer.numberOfClicksRequired = 2

    self.myView.addGestureRecognizer(doubleClickGestureRecognizer)

我认为这是最有用的答案,因为它还回答了是否在第二次鼠标按下或第二次鼠标按下时做出反应的隐含问题。当然,在某些情况下,偏离标准可能是有意义的。不幸的是,苹果本身并不完全遵循一个标准(Finder和Mail向上,Calendar向下)…如果您需要同时处理这两个问题,您通常会做什么?单击和双击。显然,如果最终结果是双击,你将不得不忽略单击?@jayarjo-在我的脑海中,我想不出任何地方,如果需要双击,那么单击一次就可以完成操作。在文本字段中,单击一次即可将光标置于特定位置。双击将突出显示整个单词。因此,在单击时移动光标是无害的。在RTS游戏(至少是暴雪的)中,单击选择单个单位,双击选择该类型的所有单位。如果你想让双击做一些与单次点击完全不同的事情,你可能需要重新思考你的整个用户体验。它奏效了。但我们应该考虑到,它破坏了几个组件的选择流程,例如NSTextView。这与mouseDown的示例问题完全相同:如果您有两个用于单击和双击的手势识别器,在双击的情况下,也会调用单键选择器。对于这个问题来说,这是过分的,不是正确的方法。Chuck的解决方案是正确的:在-mouseUp:or-mouseDown:
    let doubleClickGestureRecognizer = NSClickGestureRecognizer(target: self, action: #selector(self.myCustomMethod))
    doubleClickGestureRecognizer.numberOfClicksRequired = 2

    self.myView.addGestureRecognizer(doubleClickGestureRecognizer)