Why is this double-click detection code unreliable?

心不动则不痛 提交于 2019-12-10 11:28:32

问题


I'm trying to learn Rx through some simple challenges, first by detecting double-clicks by watching only MouseUp events. I came up with the following solution (this code is compilable by creating a WPF project and adding the Reactive Extensions NuGet package):

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));
        }
    }
}

Most solutions I've seen don't deal with multiple clicks, so the idea is to always wait for a certain interval (interClickInterval) between each double-click, and then a double-click is the next mouse up event that has an interval smaller than the intraClickInterval. I've also added a message that gets printed after the interClickInterval elapses following each double-click so that I know when double-clicks are supposed to register.

This seems to work well in general, but it seems that sometimes they do not register even though I see the "Now accepting double-click!" message. This seems to happen particularly if I click just before the message appears. What could be causing this?

EDIT: I think the double-click detection is actually correct, it's the message that isn't. Basically, it ignores any subsequent click after a double-click. I'd need to do something like

  • for each double click event
  • wait for the interClickInterval
  • if no click was registered since, display "Now accepting double click!"

But I'm not sure how to achieve that...


回答1:


So as I suspected, the detection code is correct, it's the message that was timed incorrectly. It didn't take into account any subsequent clicks after a double-click; it just always printed its message 1000ms after each double-click. Here's a version of the ready message that correctly waits for 1000ms to have elapsed since the last click after each double-click:

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

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


来源:https://stackoverflow.com/questions/23715940/why-is-this-double-click-detection-code-unreliable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!