Ловля двойного клика в Какао OSX - PullRequest
15 голосов
/ 02 февраля 2010

NSResponder, похоже, не имеет события двойного щелчка мышью.Есть ли простой способ поймать двойной щелчок?

Ответы [ 7 ]

28 голосов
/ 02 февраля 2010

Методы mouseDown: и mouseUp: принимают объект NSEvent в качестве аргумента с информацией о кликах, включая clickCount.

8 голосов
/ 21 августа 2015

Проблема с простым clickCount решением состоит в том, что двойной щелчок рассматривается просто как два одиночных щелчка. Я имею в виду, вы все еще получаете один клик. И если вы хотите по-разному реагировать на этот клик, вам нужно что-то помимо простого подсчета кликов. Вот что я закончил (в 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")
}
6 голосов
/ 20 октября 2013

NSEvent сгенерированные для mouseDown: и mouseUp: имеют свойство с именем clickCount. Проверьте, нет ли двух, чтобы определить, произошел ли двойной щелчок.

Пример реализации:

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

Просто поместите это в ваш NSResponder (например, NSView) подкласс.

5 голосов
/ 21 марта 2013

Обычно приложения обращаются к clickCount == 2 on - [mouseUp:], чтобы определить двойной щелчок.

Одним из уточнений является отслеживание местоположения щелчка мыши на - [mouseDown:] и отслеживание небольшой разницы в расположении мыши вверх (5 и менее точек как у x, так и у).

1 голос
/ 15 апреля 2018

Я реализовал нечто похожее на @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
 }
0 голосов
/ 01 октября 2018

Альтернативой методу mouseDown: + NSTimer, который я предпочитаю, является NSClickGestureRecognizer.

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

    self.myView.addGestureRecognizer(doubleClickGestureRecognizer)
0 голосов
/ 10 ноября 2015

Лично я проверяю двойной щелчок мышью по функциям mouseUp:

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

    if ([theEvent clickCount] == 2)
    {

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

     }

}
...