Cocoa OSXでダブルクリックをキャッチします
-
24-09-2019 - |
質問
NSResponderには、マウスのダブルクリックイベントがないようです。ダブルクリックをキャッチする簡単な方法はありますか?
解決
mouseDown:
と mouseUp:
メソッドは、クリックに関する情報を含む、nseventオブジェクトを引数として受け取ります。 clickCount
.
他のヒント
平野の問題 clickCount
解決策は、ダブルクリックが単純に2回のシングルクリックと見なされるということです。私はあなたがまだシングルクリックを取得することを意味します。そして、そのシングルクリックに異なる反応をしたい場合は、単なるクリックカウントに加えて何かが必要です。これが私が(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")
}
通常、アプリケーションはClickCount == 2 on- [MouseUp:]を調べて、ダブルクリックを決定します。
1つの改良は、マウスのクリックの位置を追跡することです - [Mousedown:]をクリックし、マウスアップ位置のデルタが小さいことを確認します(XとYの両方で5ポイント以下)。
NSEvent
sの生成 mouseDown:
と mouseUp:
呼ばれるプロパティがあります clickCount
. 。ダブルクリックが発生したかどうかを判断するために2つのかどうかを確認してください。
サンプルの実装:
- (void)mouseDown:(NSEvent *)event {
if (event.clickCount == 2) {
NSLog(@"Double click!");
}
}
それをあなたの中に置いてください NSResponder
( NSView
)サブクラス。
@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
}
個人的には、ダブルクリックしてMouseUp関数をチェックします。
- (void)mouseUp:(NSEvent *)theEvent
{
if ([theEvent clickCount] == 2)
{
CGPoint point = [theEvent locationInWindow];
NSLog(@"Double click on: %f, %f", point.x, point.y);
}
}
代替手段 mouseDown:
+ NSTimer
私が好む方法はです NSClickGestureRecognizer
.
let doubleClickGestureRecognizer = NSClickGestureRecognizer(target: self, action: #selector(self.myCustomMethod))
doubleClickGestureRecognizer.numberOfClicksRequired = 2
self.myView.addGestureRecognizer(doubleClickGestureRecognizer)