Как я могу предотвратить события перемещения мыши при нажатии кнопки мыши? - PullRequest
4 голосов
/ 21 сентября 2011

У меня есть сетка, по которой я хочу навести курсор мыши. Пока я просто парю и двигаю мышь, я хочу, чтобы события запускались, но когда я нажимаю mousedown, они должны приостановить стрельбу. Как только я подожду мышь, они должны продолжить.

Если это звучит очень легко, то, вероятно, это не так. Через некоторое время мы придумали не очень элегантное решение, но мне интересно, существует ли что-то лучшее. Я не буду влиять на ваш подход с нашим взломом.

Итак, исходный код, который не работает

mouseMove.TakeUntil(mouseDown).Repeat()

Добавление .SkipUntil(mouseUp) влево или вправо к TakeUntil в основном не позволяет вышеуказанному коду вообще работать.

Ответы [ 4 ]

2 голосов
/ 21 сентября 2011

Как насчет этого:

bool mouseIsDown = false;
Observable.Merge(
    mouseDown.Select(_ => true),
    mouseUp.Select(_ => false)
).Subscribe(x => mouseIsDown = x);

mouseMove.Where(_ => !mouseIsDown);

Технически правильный ответ связан с оператором Window, но это так же хорошо, и его легче поймать (и мне легче написать)

0 голосов
/ 21 сентября 2011

Это работает:

        var mouseMoveWhileUpOnly =
            mouseUp
                .Select(mu =>
                    mouseMove
                        .TakeUntil(mouseDown))
                .Switch();

Единственный трюк, который вам нужно сделать, чтобы запустить наблюдаемое без необходимости наведения мыши вручную, это:

        var mouseUp = Observable
            .FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => this.MouseLeftButtonUp += h,
                h => this.MouseLeftButtonUp -= h)
            .Select(ep => Unit.Default)
            .StartWith(Unit.Default);

Обратите внимание наStartWith.

В противном случае наблюдаемые значения mouseDown & mouseMove определяются нормально.

0 голосов
/ 21 сентября 2011

Ниже приведены 2 возможных решения

var beh = new BehaviorSubject<bool>(true);
mousedown.Select(_ => false).Subscribe(beh);
mouseup.Select(_ => true).Subscribe(beh);
mousemove.SelectMany(e =>
{
     return mousemove.TakeUntil(beh.Where(b => !b));
}).Subscribe( .... );

OR

var du = mousedown.Select(_ => false).Merge(mouseup.Select(_ => true)).Merge(Observable.Return(true));
mousemove.CombineLatest(du, (ev, b) => new Tuple<MouseEventArgs, bool>(ev.EventArgs, b))
 .Where(t => t.Item2)
 .Select(t => t.Item1)
 .Subscribe(....);
0 голосов
/ 21 сентября 2011

это может быть возможным решением

// create the observables
IObservable<Point> mouseMove = Observable.FromEventPattern<MouseEventArgs>(this, "MouseDown")
    .Select(e=>e.EventArgs.GetPosition(this));

IObservable<bool> mouseDown = Observable.FromEventPattern(this, "MouseDown").Select(_ => false);
IObservable<bool> mouseUp = Observable.FromEventPattern(this, "MouseUp").Select(_ => true);

var merged = mouseUp.Merge(mouseDown).StartWith(true);

// sends the moves with the current state of the mouse button
var all = mouseMove.CombineLatest(merged, (move, take) => new {Take = take, Move = move});

// the result is all the points from mouse move where the mouse button isn't pressed
var result = all.Where(t => t.Take).Select(t => t.Move);
...