Pregunta

NSRESPONDER parece no tener un evento de doble clic del mouse. ¿Hay una manera fácil de atrapar un doble clic?

¿Fue útil?

Solución

los mouseDown: y mouseUp: Los métodos toman un objeto nsevent como argumento con información sobre los clics, incluido el clickCount.

Otros consejos

El problema con Plain clickCount La solución es que el doble clic se considera simplemente como dos clics únicos. Quiero decir que todavía obtienes el simple clic. Y si desea reaccionar de manera diferente a ese solo clic, necesita algo además del solo clic del clic. Esto es lo que terminé (en Swift):

private var _doubleClickTimer: NSTimer?

// a way to ignore first click when listening for double click
override func mouseDown(theEvent: NSEvent) {
    if theEvent.clickCount > 1 {
        _doubleClickTimer!.invalidate()
        onDoubleClick(theEvent)
    } else if theEvent.clickCount == 1 { // can be 0 - if delay was big between down and up
        _doubleClickTimer = NSTimer.scheduledTimerWithTimeInterval(
            0.3, // NSEvent.doubleClickInterval() - too long
            target: self,
            selector: "onDoubleClickTimeout:",
            userInfo: theEvent,
            repeats: false
        )
    }
}


func onDoubleClickTimeout(timer: NSTimer) {
    onClick(timer.userInfo as! NSEvent)
}


func onClick(theEvent: NSEvent) {
    println("single")
}


func onDoubleClick(theEvent: NSEvent) {
    println("double")
}

En general, las aplicaciones analizan ClickCount == 2 en -[MouseUp:] para determinar un doble clic.

Un refinamiento es realizar un seguimiento de la ubicación del clic del mouse en -[MouseDown:] y ver que el delta en la ubicación del mouse es pequeño (5 puntos o menos en la X y la y).

los NSEvents Generado para mouseDown: y mouseUp: tener una propiedad llamada clickCount. Compruebe si son dos para determinar si ha ocurrido un doble clic.

Implementación de la muestra:

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

Solo coloca eso en tu NSResponder (como un NSView) subclase.

Implementé algo similar a @jayarjo, excepto que esto es un poco más modular, ya que podría usarlo para cualquier NSVIEW o una subclase. Este es un reconocimiento de gestos personalizado que reconocerá acciones de clic y doble, pero no solo clics hasta que haya pasado el umbral de doble clic:

//
//  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
    }
}

Uso:

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
 }

Personally, I check the double click into mouseUp functions:

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

    if ([theEvent clickCount] == 2)
    {

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

     }

}

An alternative to the mouseDown: + NSTimer method that I prefer is NSClickGestureRecognizer.

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

    self.myView.addGestureRecognizer(doubleClickGestureRecognizer)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top