Как предотвратить вызов функции одного клика в функции двух кликов?

Я пытаюсь добавить собственное поведение к своим кнопкам. Если нажать один раз - выполняется одно действие. Если щелкнуть два раза, выполняется еще один.

Я видел такое решение в этом ответе и пробовал все возможные комбинации:

        clickOnce.shouldBeRequiredToFailByGestureRecognizer(clickTwice)
        clickTwice.shouldBeRequiredToFailByGestureRecognizer(clickOnce)
        clickOnce.shouldRequireFailureOfGestureRecognizer(clickTwice)
        clickTwice.shouldRequireFailureOfGestureRecognizer(clickOnce)
        clickOnce.canPreventGestureRecognizer(clickTwice)
        clickOnce.canBePreventedByGestureRecognizer(clickTwice)
        clickTwice.canPreventGestureRecognizer(clickOnce)
        clickTwice.canBePreventedByGestureRecognizer(clickOnce)

Но у меня ничего не получалось.

А вот и полный код:

import Cocoa

class ViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        let buttonTestOne = NSButton(frame: CGRect(x: 500, y: 500, width: 100, height: 500))

        let clickOnceForTestOne = NSClickGestureRecognizer(target: buttonTestOne, action: #selector(ViewController.clickOneTime(_:)))
        clickOnceForTestOne.numberOfClicksRequired = 1
        buttonTestOne.addGestureRecognizer(clickOnceForTestOne)
        self.view.addSubview(buttonTestOne)

        let arrTestButtons = ["One", "Two", "Three"]

        var x = 0
        var y = 0

        for item in arrTestButtons{
            let buttonNew = NSButton(frame: CGRect(x: x, y: y, width: 100, height: 100))
            x = x + 120
            y = y + 120
            buttonNew.attributedTitle = NSAttributedString(string: item)
            let clickOnce = NSClickGestureRecognizer(target: self, action: #selector(ViewController.clickOneTime(_:)))
            clickOnce.numberOfClicksRequired = 1
            buttonNew.addGestureRecognizer(clickOnce)
            let clickTwice = NSClickGestureRecognizer(target: self, action: #selector(ViewController.clickTwoTimes(_:)))
            clickTwice.numberOfClicksRequired = 2
            buttonNew.addGestureRecognizer(clickTwice)
            clickOnce.shouldBeRequiredToFailByGestureRecognizer(clickTwice)
            clickTwice.shouldBeRequiredToFailByGestureRecognizer(clickOnce)
            clickOnce.shouldRequireFailureOfGestureRecognizer(clickTwice)
            clickTwice.shouldRequireFailureOfGestureRecognizer(clickOnce)
            clickOnce.canPreventGestureRecognizer(clickTwice)
            clickOnce.canBePreventedByGestureRecognizer(clickTwice)
            clickTwice.canPreventGestureRecognizer(clickOnce)
            clickTwice.canBePreventedByGestureRecognizer(clickOnce)

            self.view.addSubview(buttonNew)
        }


    }

    func clickOneTime(g:NSClickGestureRecognizer){
        if g.state == .Ended {
            Swift.print("single click")
        }
    }
    func clickTwoTimes(g: NSClickGestureRecognizer){
        if g.state == .Ended {
            Swift.print("DOUBLE CLICK!")
        }
    }
    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

Что я делаю неправильно? Я думаю, что ошибка должна быть довольно простой, я либо звоню не с того места, либо что-то в этом роде, но я не могу понять.

Вот лог-файл, одинаковый для всех комбинаций:

Нажал один раз:

single click

Как и ожидалось

Щелкнул дважды:

single click
DOUBLE CLICK!

Который запускает как одиночный, так и двойной щелчок.

Я прочитал документацию. И я пробовал все комбинации, потому что не мог найти решение.

Я также пробовал с журналами. Итак, Swift.print(clickOnce.shouldBeRequiredToFailByGestureRecognizer(clickTwice)) и один из них, но это дает мне false.


person Anna-Lischen    schedule 15.05.2016    source источник
comment
Вы не можете просто смешать все виды строк кода вместе и ожидать, что код будет работать так, как ожидалось. Прочтите документацию для каждого из методов, которые вы вызываете, и попытайтесь выяснить, какой распознаватель жестов может каким образом влиять на другой.   -  person luk2302    schedule 15.05.2016
comment
Пример, на который вы ссылаетесь, относится к iOS, а не к OS X, поэтому двойное нажатие мышью, вероятно, не будет иметь такого же эффекта, как двойное нажатие пальцем на устройстве. Кроме того, у меня ничего не получилось, это не указывает на то, как это не работает, и вы должны объяснить это в своем вопросе.   -  person l'L'l    schedule 15.05.2016
comment
@luk2302 luk2302 Я не смешивал их все, я просто попробовал все комбинации и опубликовал такой код для краткости.   -  person Anna-Lischen    schedule 15.05.2016
comment
Сомневаюсь, что вы пробовали их все, их 2^8, то есть 256 комбинаций. Прислушайтесь к моему совету и прочтите документацию.   -  person luk2302    schedule 15.05.2016
comment
@ luk2302 Я прочитал документацию, хорошо, я не пробовал все 256 комбинаций, но я попробовал то, что показалось мне наиболее логичным из документации. Каждый по отдельности и вместе. По крайней мере, если бы могла быть комбинация для работы, она бы появилась.   -  person Anna-Lischen    schedule 15.05.2016
comment
Вы пробовали только clickOnce.shouldRequireFailureOfGestureRecognizer(clickTwice)?   -  person luk2302    schedule 15.05.2016
comment
@ luk2302 Да, конечно. Это был фактически первый вариант, который я попробовал. В наборе из всех, что я пробовала, он сейчас третий, хотя попробовал его первым. Вот как пробовал и проверял: clickOnce.shouldRequireFailureOfGestureRecognizer(clickTwice) и Swift.print("TEST!!!!", clickOnce.shouldRequireFailureOfGestureRecognizer(clickTwice)) А вот лог: TEST!!!! false TEST!!!! false TEST!!!! false single click single click DOUBLE CLICK! Первые три строчки работают при прогоне цикла, последние три - при клике. Таким образом, он ставит false с самого начала.   -  person Anna-Lischen    schedule 15.05.2016


Ответы (3)


Попробуй это:

let click = NSClickGestureRecognizer(target: self, action: #selector(clicked(_:))
click.numberOfClicksRequired = 2
person Harry Ng    schedule 12.02.2017

Я пытался решить это сам; оказывается, что решение относительно простое.

Используйте распознаватель жестов для двойного щелчка (здесь я добавил их в представление, но тот же принцип должен работать для кнопок)

let doubleClickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(ViewController.clickTwice))
doubleClickRecognizer.numberOfClicksRequired = 2
self.view?.addGestureRecognizer(doubleClickRecognizer)

Добавлять

@objc func clickTwice() {
    print("double click")
}

а затем обрабатывать одиночные клики через

override func mouseDown(with event: NSEvent) {
    print("mouse down; once")
}

(или соответствующий эквивалент).

NSGestureRecognizer имеет

var delaysPrimaryMouseButtonEvents: Bool

для которого по умолчанию установлено значение true, поэтому с этой комбинацией он ждет, пока doubleClickRecognizer не обработает двойной щелчок, прежде чем перейти вверх по цепочке респондентов, чтобы увидеть, кто еще заинтересован в щелчке мыши.

Два распознавателя жестов имеют ту же проблему, что и обработка одиночных и двойных щелчков мыши в mouseDown: сначала срабатывает одиночный щелчок. Чтобы преодолеть это, вам нужно переопределить

func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool  

Это не функция, которую вы вызываете, это функция делегата, которую вы переопределяете. Таким образом, вы устанавливаете свой viewController в соответствии с NSGestureRecognizerDelegate (что означает, что он будет получать методы делегата); установите singleClickRecognizer.delegate = self (где self — ваш viewController) и реализуйте

func gestureRecognizer(_ gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: NSGestureRecognizer) -> Bool {
    if gestureRecognizer == singleClickRecognizer && otherGestureRecognizer == doubleClickRecognizer {
        return true
    }
    return false
    }

в котором говорится, что ваш singleClickRecognizer ожидает сбоя doubleClickRecognizer перед выполнением своего селектора.

К сожалению, я обнаружил, что в SpriteKit, хотя этот код делает то, что он говорит на жестяной банке (сначала обрабатывает двойной щелчок), это приводит к неприемлемым задержкам, поэтому я не уверен, что могу его рекомендовать.

person green_knight    schedule 14.08.2018

Может быть, вы могли бы попробовать это так, где «кнопка» — это ваша кнопка.

let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.clickTwoTimes(_:)))
let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.clickOneTime(_:)))
singleTapRecognizer.numberOfTapsRequired = 1
doubleTapRecognizer.numberOfTapsRequired = 2
button.addGestureRecognizer(doubleTapRecognizer)
button.addGestureRecognizer(singleTapRecognizer)
singleTapRecognizer.requireGestureRecognizerToFail(doubleTapRecognizer)
person Jamal    schedule 15.05.2016
comment
Это iOS, и я пытаюсь найти решение для OS X. - person Anna-Lischen; 15.05.2016