2014-11-13 5 views
0

Windows Forms 응용 프로그램이 있고 Rx를 사용하여 MouseMove 이벤트 스트림을 쿼리하고 마우스의 위치 (현재 및 이전)를 기반으로 결과를 생성합니다. 합니다 (LABEL1 결과를 보여주고 라벨 2는 현재 및 이전 위치로 "로그인"을 보여줍니다.)MouseMove 이벤트 스트림 비교 마우스 위치가 감소하지 않습니다.

 var observable = Observable.FromEventPattern<MouseEventArgs>(this, "MouseMove"); 
     observable     
      .PairWithPrevious() 
      .Select(tuple => 
        { 
         if (tuple.Item2 == null || tuple.Item1 == null) return Tuple.Create(0, 0); 
         var currPosition = tuple.Item2.EventArgs.Location; 
         var prevPosition = tuple.Item1.EventArgs.Location; 
         var x = 0; 
         if (currPosition.X > prevPosition.X) x = 1; 
         else if (currPosition.X < prevPosition.X) x = -1; 
         var y = 0; 
         if (currPosition.Y > prevPosition.Y) y = 1; 
         else if (currPosition.Y < prevPosition.Y) y = -1; 
         label2.Text = string.Format("Curr X: {0} * Y: {1} |||| Prev X: {2} * Prev Y: {3}", currPosition.X, currPosition.Y, prevPosition.X, prevPosition.Y); 
         return Tuple.Create(x, y); 
        }) 
      .Subscribe(x => 
         { 
          label1.Text = string.Format("X: {0} ** Y: {1}", x.Item1, x.Item2); 
         }); 

PairWithPrevious 기능 : 같은 내 코드 보인다

public static IObservable<Tuple<TSource, TSource>> PairWithPrevious<TSource>(this IObservable<TSource> source) 
    { 
     return source.Scan(
      Tuple.Create(default(TSource), default(TSource)), 
      (acc, current) => Tuple.Create(acc.Item2, current)); 
    } 

문제는 다음과 같은 경우 마우스를 왼쪽 또는 위로 이동하면 이전 및 현재 (x, y)는 같은 값이고 결과 (label1)는 "-1"값을 표시하지 않습니다.

나는 이전과 현재 값을 비교하기 위해 우편 기능을 사용하여 시도했지만, 결과는 동일합니다

 Zip(observable.Skip(1), Tuple.Create) 

그래서, 왜이 발생? 그것을 고치는 방법?

+0

값이 같으면 항상 -1을 얻습니다. ('currPosition.X> prevPosition.X'는 항상'false'를 반환합니다). 그래서 뭔가 다른 코드가 의심됩니다. 이것은 완전한 샘플입니까? –

+0

Rx 쿼리에 문제가없는 것 같습니다. –

+0

'Publish '도 사용하지 않으면'Zip' 예제가 작동하지 않을 것입니다. 그러나'Scan'은 괜찮습니다. ('스캔'은 내가 선호하는 페어링 방법입니다.) –

답변

0

MouseMove 이벤트가 발생하는 빈도를 보면 문제의 원인을 알 수 있습니다. 개수를 포함하도록 코드를 업데이트했습니다. 또한 세 개의 열이있는 간단한 listview를 추가하고 Listview의 뷰를 세부적으로 설정하여 매우 잘 보입니다.

일부 코드는 귀하의 것과 다릅니다. 주로 스타일 문제입니다. 하지만 난 그냥 WithPrevious로 PairWithPrevious을 변경하고 튜플

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

RX 선택 연산자는 단지 카운터 INT의 과부하를 가지고 숨겼다. 나는 이것을 사용하여 익명 객체를 추가하여 체인을 연결합니다. WithPrevious 이제 그냥 우리가 원하는 데이터가 포함 된 다른 익명의 개체를 밖으로 프로젝트. 그런 다음 구독 할 때 두 레이블과 새 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); 
             }); 
당신이 나에 마우스를 이동하는 경우 줄이거 나 이벤트가 발생 한 번만 오른쪽하지만 마우스를 이동 속도가 느린 경우 이제 볼 수

은 내 컴퓨터에, 이벤트의 가장 작은 수를 왼쪽 I 얻을 수있는 것은 3이고 마지막 것은 항상 이전 것과 같습니다. 그것이 항상 0 인 이유입니다.

이제 우리가 .DistinctUntilChanged (a => a.CurrentPoint)를 WithPrevious 바로 뒤에 추가하고 구독하기 전에 더 많은 정보를 얻을 수 있습니다. 마우스 대각선을 움직이면 내 PC의 이벤트가 X와 Y를 모두 가지지 않기 때문에 가장 많이 알 수 있습니다. Throttle을 사용하여 주위를 놀 수도 있습니다 .Throttle (TimeSpan.FromMilliseconds (25), CurrentThreadScheduler.Instance) Select와 WithPrevious 후에. 그건 내 PC에서 도움이되었지만 완벽하지는 않았다.

+0

: o이 게시물에 대한 의견의 작성자입니다 ... 도움을 주셔서 감사합니다! – Nicolocodev

+0

DistinctUntilChanged를 사용하면 내 컴퓨터에서 잘 작동하지만 스로틀을 사용하면 다른 결과가 나타납니다. 조언이 필요하면 변경 사항을 적용하고 코드로 재생하겠습니다 ... 댓글을 달았습니다. :피. 다시 한번 감사드립니다. – Nicolocodev

관련 문제