具体而言,如果按下按键的持续时间大于阈值(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;
}
}
答案 0 :(得分: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');
答案 1 :(得分: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();