通过一个可观察/响应扩展来检测鼠标移动的开始和停止
本文关键字:移动 鼠标 检测 开始 扩展 响应 一个 观察 | 更新日期: 2023-09-27 18:07:24
让我从:
开始- 我对Rx完全陌生
- 我已经不再使用c#/Linq
- 我正在试验/学习,所以没有应用程序使用来解决这个问题
我读了一些介绍性的内容,包括Matthew 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);
});
我的问题
基于这个例子,我想尝试对鼠标移动做出反应,这样:
- 当鼠标移动时,我将
someCanvas
的背景色设置为绿色 - 当鼠标不移动时,我将背景色设置为红色
鼠标左键不涉及,只是鼠标移动。
这可能吗?
我认为这里的关键是鼠标何时不移动?当它空闲了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.
我将第一个告诉你,我怀疑这不是最好的解决方案。缓冲鼠标移动事件似乎是不必要的浪费。我试图使用?Sample
找到解决方案,但我无法使其工作。
由于Jerry的评论,我对更新后的解决方案更满意了。
首先,这里有一个问题:
var mouseDiffs = mouseMoves.Skip(1)
.Zip(mouseMoves, (l, r) => new { X1 = l.X, Y1 = l.Y, X2 = r.X, Y2 = r.Y });
当观察者订阅mouseDiffs
时,对mouseMoves
进行两次订阅。您应该使用Publish
,以确保每次订阅mouseDiffs
只订阅一次mouseMoves
:
var mouseDiffs = mouseMoves.Publish(obs => obs.Skip(1)
.Zip(obs, (l, r) => new { X1 = l.X, Y1 = l.Y, X2 = r.X, Y2 = r.Y }));
现在让我们为画布定义一个可观察的颜色。注意,你实际上不需要mouseDiffs
可观察对象,mouseMove
就可以了。
var colors = mouseMove
.Select(_ => Observable.Concat(
Observable.Return(true),
Observable.Return(false).Delay(TimeSpan.FromSeconds(1))))
.Switch()
.StartWith(false)
.DistinctUntilChanged()
.Select(isActive => isActive ? Color.Green : Color.Red);
你可以设置Subscribe
到colors
,并设置你的画布颜色,每次它发出一个Color