C# 比较MouseMove事件流,鼠标位置不';不减少

C# 比较MouseMove事件流,鼠标位置不';不减少,c#,winforms,system.reactive,C#,Winforms,System.reactive,我有一个Windows窗体应用程序,我正在使用Rx查询MouseMove事件流,并根据鼠标的位置(当前和以前)生成一个结果。我的代码如下所示: (label1显示结果,label2显示带有当前和以前位置的“日志”。) 那么,为什么会发生这种情况呢?以及如何修复它?如果您观察MouseMove事件触发的频率,您将看到导致问题的原因。我已更新了您的代码以包含计数。我还添加了一个包含三列的简单listview,并将listview的视图设置为detail,使其非常可见 我的一些代码与你的不同。这主要是

我有一个Windows窗体应用程序,我正在使用Rx查询MouseMove事件流,并根据鼠标的位置(当前和以前)生成一个结果。我的代码如下所示: (label1显示结果,label2显示带有当前和以前位置的“日志”。)


那么,为什么会发生这种情况呢?以及如何修复它?

如果您观察MouseMove事件触发的频率,您将看到导致问题的原因。我已更新了您的代码以包含计数。我还添加了一个包含三列的简单listview,并将listview的视图设置为detail,使其非常可见

我的一些代码与你的不同。这主要是一个风格问题。但我将PairWithPrevious更改为刚好与Previous并隐藏了元组

//http://www.zerobugbuild.com/?p=213 with a tweak to hide the Tuple
public static IObservable<TResult> WithPrevious<TSource, TResult>(this IObservable<TSource> source, Func<TSource, TSource, TResult> projection)
{
    return source.Scan(Tuple.Create(default(TSource), default(TSource)),
                       (previous, current) => Tuple.Create(previous.Item2, current))
                 .Select(t => projection(t.Item1, t.Item2));
}
//http://www.zerobugbuild.com/?p=213 通过调整隐藏元组
公共静态IObservable with Previous(此IObservable源,Func投影)
{
返回source.Scan(Tuple.Create(默认(TSource),默认(TSource)),
(previous,current)=>Tuple.Create(previous.Item2,current))
.选择(t=>projection(t.Item1,t.Item2));
}
RX Select运算符的int过载只是一个计数器。我将使用它来添加到一个匿名对象以向下链接。WithPrevious现在只是投影到另一个包含我们所需数据的匿名对象。然后在subscribe中,我们将更新两个标签和新的listview

var observable = Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
                                   .Select((eventPattern, count) => new {eventPattern.EventArgs, Count = count})
                                   .WithPrevious((previous, current) =>
                                       {
                                           var currentPoint = current == null
                                                                  ? new Point(0, 0)
                                                                  : current.EventArgs.Location;
                                           var previousPoint = previous == null
                                                                   ? new Point(0, 0)
                                                                   : previous.EventArgs.Location;

                                           return
                                               new
                                                   {
                                                       CurrentPoint = currentPoint,
                                                       PreviousPoint = previousPoint,
                                                       Count = current == null ? 0 : current.Count
                                                   };
                                       })
                                   .Subscribe(a =>
                                       {
                                           label2.Text =
                                               String.Format(
                                                   "Curr X: {0} * Y: {1} |||| Prev X: {2} * Prev Y: {3} - Count = {4}",
                                                   a.CurrentPoint.X, a.CurrentPoint.Y,
                                                   a.PreviousPoint.X, a.PreviousPoint.Y,
                                                   a.Count);


                                           label1.Text = String.Format("X: {0} ** Y: {1}",
                                                                       a.CurrentPoint.X.CompareTo(
                                                                           a.PreviousPoint.X),
                                                                       a.CurrentPoint.Y.CompareTo(
                                                                           a.PreviousPoint.Y));
                                           var listItem = new ListViewItem(a.Count.ToString());
                                           listItem.SubItems.Add(a.CurrentPoint.X.ToString());
                                           listItem.SubItems.Add(a.CurrentPoint.Y.ToString());
                                           listView1.Items.Add(listItem);
                                           listView1.EnsureVisible(listView1.Items.Count - 1);
                                       });
var observable=observable.FromEventPattern(这是“MouseMove”)
.Select((eventPattern,count)=>new{eventPattern.EventArgs,count=count})
.WithPrevious((先前,当前)=>
{
var currentPoint=current==null
?新点(0,0)
:current.EventArgs.Location;
var previousPoint=previous==null
?新点(0,0)
:previous.EventArgs.Location;
返回
新的
{
CurrentPoint=CurrentPoint,
PreviousPoint=PreviousPoint,
Count=current==null?0:current.Count
};
})
.订阅(a=>
{
标签2.文本=
字符串格式(
“Curr X:{0}*Y:{1}| | | | | Prev X:{2}*Prev Y:{3}-Count={4}”,
a、 CurrentPoint.X,a.CurrentPoint.Y,
a、 PreviousPoint.X,a.PreviousPoint.Y,
a、 计数);
label1.Text=String.Format(“X:{0}**Y:{1}”,
a、 CurrentPoint.X.比较(
a、 上一点X),
a、 当前点Y.比较(
a、 上一点(Y));
var listItem=new ListViewItem(a.Count.ToString());
添加(a.CurrentPoint.X.ToString());
添加(a.CurrentPoint.Y.ToString());
listView1.Items.Add(listItem);
listView1.EnsureRevible(listView1.Items.Count-1);
});
你现在可以看到,如果你正在缓慢地将鼠标向下移动或向右移动,事件只会触发一次,但是,在我的计算机上,如果你将鼠标向上移动或向左移动,我可以得到的最小事件数是三个,最后一个事件始终与前一个相同。这就是为什么它总是零,零


现在,如果我们在WithPrevious之后和Subscribe之前添加.DistinctUntilChanged(a=>a.CurrentPoint),您可以获得更多您想要的内容。我之所以这么说,是因为在我的电脑上,将鼠标沿对角线方向移动,事件的X和Y就不会有什么不同。您可能可以在Select之后和previous之前使用Throttle,比如.Throttle(TimeSpan.frommissions(25),CurrentThreadScheduler.Instance)。这在我的电脑上很有用,但并不完美。

如果它们是相同的值,那么你总是会得到-1。(
currPosition.X>prevPosition.X
将始终返回
false
)。所以我怀疑你的代码还有其他问题。这是完整的示例吗?请注意,您的Rx查询似乎没有问题。除非您也使用了
Publish
,否则您的
Zip
示例将无法正常工作,但是
Scan
很好。(
Scan
是我首选的配对方式。)您好@DaveSexton,是的,这是完整的示例。:o您是本文评论的作者。。。谢谢你的帮助!使用DistinctUntilChanged在我的机器上运行良好,但使用油门(我以前尝试过)会产生不同的结果。。。如果我需要任何建议,我将应用更改并使用代码。。。我会评论的
      Zip(observable.Skip(1), Tuple.Create)
//http://www.zerobugbuild.com/?p=213 with a tweak to hide the Tuple
public static IObservable<TResult> WithPrevious<TSource, TResult>(this IObservable<TSource> source, Func<TSource, TSource, TResult> projection)
{
    return source.Scan(Tuple.Create(default(TSource), default(TSource)),
                       (previous, current) => Tuple.Create(previous.Item2, current))
                 .Select(t => projection(t.Item1, t.Item2));
}
var observable = Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove")
                                   .Select((eventPattern, count) => new {eventPattern.EventArgs, Count = count})
                                   .WithPrevious((previous, current) =>
                                       {
                                           var currentPoint = current == null
                                                                  ? new Point(0, 0)
                                                                  : current.EventArgs.Location;
                                           var previousPoint = previous == null
                                                                   ? new Point(0, 0)
                                                                   : previous.EventArgs.Location;

                                           return
                                               new
                                                   {
                                                       CurrentPoint = currentPoint,
                                                       PreviousPoint = previousPoint,
                                                       Count = current == null ? 0 : current.Count
                                                   };
                                       })
                                   .Subscribe(a =>
                                       {
                                           label2.Text =
                                               String.Format(
                                                   "Curr X: {0} * Y: {1} |||| Prev X: {2} * Prev Y: {3} - Count = {4}",
                                                   a.CurrentPoint.X, a.CurrentPoint.Y,
                                                   a.PreviousPoint.X, a.PreviousPoint.Y,
                                                   a.Count);


                                           label1.Text = String.Format("X: {0} ** Y: {1}",
                                                                       a.CurrentPoint.X.CompareTo(
                                                                           a.PreviousPoint.X),
                                                                       a.CurrentPoint.Y.CompareTo(
                                                                           a.PreviousPoint.Y));
                                           var listItem = new ListViewItem(a.Count.ToString());
                                           listItem.SubItems.Add(a.CurrentPoint.X.ToString());
                                           listItem.SubItems.Add(a.CurrentPoint.Y.ToString());
                                           listView1.Items.Add(listItem);
                                           listView1.EnsureVisible(listView1.Items.Count - 1);
                                       });