Почему этот код обнаружения двойного щелчка ненадежен?


Я пытаюсь изучить Rx с помощью некоторых простых задач, сначала обнаруживая двойные щелчки, наблюдая только за событиями MouseUp. Я придумал следующее решение (этот код компилируется путем создания проекта WPF и добавления пакета реактивных расширений NuGet):

using System;
using System.Reactive.Linq;
using System.Windows.Input;

namespace WpfApplication1 {
    public partial class MainWindow {
        public MainWindow() {
            InitializeComponent();
            var clickEvents = Observable
                .FromEventPattern<MouseButtonEventArgs>(this, "MouseLeftButtonUp");

            var intraClickInterval = TimeSpan.FromMilliseconds(500);
            var interClickInterval = TimeSpan.FromMilliseconds(1000);

            var doubleClicks = clickEvents
                .TimeInterval()
                .SkipWhile(t => t.Interval < interClickInterval)
                .FirstAsync(t => t.Interval < intraClickInterval)
                .Repeat();

            var doubleClickReady = doubleClicks
                .Delay(interClickInterval)
                .Subscribe(e => Console.WriteLine("Now accepting double click!"));

            doubleClicks.Subscribe(e => Console.WriteLine(e.Interval));
        }
    }
}

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

Это, кажется, работает хорошо в целом, но кажется, что иногда они не регистрируются, хотя я вижу " теперь принимаю двойной щелчок!" сообщение. Это, кажется, происходит особенно, если я нажимаю непосредственно перед появлением сообщения. Что может быть причиной вот это?

EDIT: я думаю, что обнаружение двойного щелчка на самом деле правильно, это сообщение, которое не является. в основном, он игнорирует любой последующий щелчок после двойного щелчка. Мне нужно было бы сделать что-то вроде

  • для каждого события двойного щелчка
  • дождитесь интеркликинтервала
  • если с тех пор не было зарегистрировано ни одного щелчка, выведите на экран сообщение " Теперь принимаю двойной щелк!"

Но я не уверен, как этого добиться...

1 2

1 ответ:

Итак, как я и подозревал, код обнаружения верен,это сообщение, которое было рассчитано неправильно. Он не учитывал никаких последующих кликов после двойного щелчка; он просто всегда печатал свое сообщение 1000 мс после каждого двойного щелчка. Вот версия готового сообщения, которое корректно ожидает 1000 мс, прошедших с момента последнего щелчка после каждого двойного щелчка:

        var doubleClickReady = doubleClicks
            .SelectMany(clickEvents
                .Buffer(interClickInterval)
                .FirstAsync(b => b.Count == 0));

        doubleClickReady
            .Subscribe(e => Console.WriteLine("Now accepting double click!"));