使用Observable/Reactive Extensions检测鼠标移动的开始和停止?

Gav*_*ope 1 c# linq system.reactive

让我先说:

  1. 我对Rx完全不熟悉
  2. 我没有使用C#/ Linq练习
  3. 我正在进行实验/学习,因此这个问题没有应用

我读过一些介绍内容,包括本介绍无框架马修Podwysocki.

所以我从他的一个例子开始,写了一些像这样的鼠标拖动/绘图代码:

var leftMouseDown = Observable.FromEventPattern<MouseEventArgs>(mainCanvas, "MouseLeftButtonDown");
var leftMouseUp = Observable.FromEventPattern<MouseButtonEventArgs>(mainCanvas, "MouseLeftButtonUp");
var mouseMove = Observable.FromEventPattern<MouseEventArgs>(mainCanvas, "MouseMove");

var mouseMoves = from mm in mouseMove
                 let location = mm.EventArgs.GetPosition(mainCanvas)
                 select new { location.X, location.Y };

var mouseDiffs = mouseMoves.Skip(1).Zip(mouseMoves, (l, r) => new { X1 = l.X, Y1 = l.Y, X2 = r.X, Y2 = r.Y });

var mouseDrag = from _ in leftMouseDown
                from md in mouseDiffs.TakeUntil(leftMouseUp)
                select md;

var mouseSub = mouseDrag.Subscribe(item =>
{
     var line = new Line
     {
         Stroke = Brushes.LightSteelBlue,
         X1 = item.X1,
         X2 = item.X2,
         Y1 = item.Y1,
         Y2 = item.Y2,
         StrokeThickness = 5
     };
     mainCanvas.Children.Add(line);
 });
Run Code Online (Sandbox Code Playgroud)

我的问题

基于这个例子,我想尝试对鼠标移动做出反应,这样:

  • 当鼠标移动时,我将背景颜色设置someCanvas为绿色
  • 当鼠标不移动时,我将背景颜色设置为红色

涉及鼠标左键,只是鼠标移动.

那可能吗?

Jas*_*oyd 5

我认为这里的关键是什么时候鼠标不动?当它空闲1秒,10秒,250毫秒?以下应该做你想要的.它是一种可观察的类型bool.true当鼠标移动并且false鼠标空闲时间长于指定的空闲时间时,它会产生.

int idleTime = 1000;

var mouseMoving =
    mouseMove
    .Buffer(TimeSpan.FromMilliseconds(idleTime), 1) // Buffer the mouse move events for the duration of the idle time.
    .Select(x => x.Any())                           // Return true if the buffer is not empty, false otherwise.
    .DistinctUntilChanged();                        // Only notify when the mouse moving state changes.
Run Code Online (Sandbox Code Playgroud)

我会第一个告诉你我怀疑这不是最好的解决方案.缓冲鼠标移动事件似乎是不必要的浪费.我试图找到一个解决方案,Sample但我无法做到这一点.

由于Jerry的评论,我对更新后的解决方案更加满意.

  • 我认为如果你还将容量限制为1传递给缓冲区,那么你将获得更具响应性的结果.一旦缓冲区中包含任何内容,我们就知道您应该发出false并再次启动限时缓冲区. (2认同)