1

具体的には、キーがしきい値 (T) よりも長い間押し下げられた場合に、アクションの実行をシミュレートしようとしています。

状態変数なしでReactive Extensions .NET (安定した 1.0 バージョン) を使用してこれを実行しようとしています。

これが私の入力と必要なもののマーブルダイアグラムです:

T = 3 とします (したがって、キーアップ イベントのない 4 dddd は「キーが押された状態」を構成します)

keyDown: --dddd---dd--d-dddddddddd----

keyUp: -----------u-----u--u---------------u--

希望: ------a-------a----------

これは私が思いついたコードの例ですが、状態変数を使用しています。

var keyDownStream = Observable.FromEventPattern<KeyEventArgs>(this, "KeyDown").Where(args => args.EventArgs.Key == Key.OemPeriod);
        var keyUpStream = Observable.FromEventPattern<KeyEventArgs>(this, "KeyUp").Where(args => args.EventArgs.Key == Key.OemPeriod);

        var repeatGuard = false;
        keyUpStream.Subscribe(x => repeatGuard = false);
        keyDownStream
            .DelayOrCancel(TimeSpan.FromSeconds(2.0), keyUpStream)
            .Where(_ => repeatGuard == false)
            .Do(_ =>
            {
                repeatGuard = true;
            })
            .Subscribe(
                result =>
                {
                    Console.WriteLine("KeyHold");
                }
            );

public static class JustinsRx
{
    public static IObservable<T> DelayOrCancel<T, TCancel>(this IObservable<T> source,
                                     TimeSpan delay,
                                     IObservable<TCancel> cancel)
    {
        //argument checking skipped
        return from s in source
               from i in Observable.Timer(delay).TakeUntil(cancel)
               select s;
    }
}
4

2 に答える 2

2

これはうまくいきますが、もっと短くできると思います。

var firstKeyDowns = Observable
    .Merge(keyDownStream.Select(_ => 'd'), keyUpStream.Select(_ => 'u'))
    .DistinctUntilChanged()
    .Where(c => c == 'd');
var query = from s in firstKeyDowns 
            from i in Observable.Timer(delay).TakeUntil(keyUpStream)
            select s;

編集:これは私が少し良いと思う別のバージョンです:

var noRepeats = Observable
    .Merge(keyDownStream.Select(_ => 'd'), keyUpStream.Select(_ => 'u'))
    .DistinctUntilChanged();
var query = noRepeats
    .Throttle(delay)
    .Where(c => c == 'd');
于 2012-04-05T03:56:17.580 に答える
1

これは私のために働いた:

var timer = Observable.Timer(TimeSpan.FromSeconds(1.0));

var query =
    keyDownStream
        .Select(_ =>
            keyUpStream
                .Select(_ => 'u')
                .Amb(timer.Select(_ => 't'))
                .Take(1)
                .Where(x => x == 'u')
                .Select(_ => Unit.Default))
        .Switch();
于 2012-04-05T03:09:49.777 に答える