【问题标题】:Time flies like an arrow demo in WinForms时间过得像 WinForms 中的箭头演示
【发布时间】:2010-03-18 06:35:13
【问题描述】:

查看Jeff Van Gogh's blog 上的 Reactive Extensions for javascript 演示,我想我应该在 C#/Winforms 中尝试一下,但它似乎不太好用。

我只是把它扔到一个表单的构造函数中(安装并引用了 Rx 框架):

Observable.Context = SynchronizationContext.Current;
var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove");
var message = "Time flies like an arrow".ToCharArray();

for(int i = 0; i < message.Length; i++)
{
    var l = new Label() 
            { 
                Text = message[i].ToString(), 
                AutoSize = true, 
                TextAlign = ContentAlignment.MiddleCenter 
            };
    int closure = i;
    mousemove
        .Delay(closure * 150)
        .Subscribe(e => 
            {
                l.Left = e.EventArgs.X + closure * 15 + 10;
                l.Top = e.EventArgs.Y;
                //Debug.WriteLine(l.Text);
            });
    Controls.Add(l);
}

当我移动鼠标时,字母似乎以随机顺序移动,如果我取消注释 Debug 行,我会看到同一个字母的多个事件...

有什么想法吗?我试过Throttle,但它似乎没有任何区别。我是否只是要求 WinForms 移动所有这些标签?

(在Rx Forum上发帖)

【问题讨论】:

    标签: c# winforms system.reactive


    【解决方案1】:

    Rx Forum 发回的答案交叉(如果作者在这里并且想要声明它,我可以):

    问题 #1:您使用的是旧位。 Observable.Context 大约在 4 个版本前消失了。 问题 #2:Javascript 没有线程的概念,Rx 喜欢为你把东西放在其他线程上。

    因此,使用最新的位,解决方案看起来像这样:

    void Form1_Load(object sender, EventArgs e)
    {
       Reactive("Time flies like an arrow");
    }
    
    private void Reactive(string msg)
    {
        var mousemove = Observable.FromEvent<MouseEventArgs>(this, "MouseMove");
        var message = msg.ToCharArray();
    
        for(int i = 0; i < message.Length; i++)
        {
            var l = new Label()
            { 
                Text = message[i].ToString(), 
                AutoSize = true, 
                TextAlign = ContentAlignment.MiddleCenter 
            };
            int closure = i;
            mousemove
                .Delay(TimeSpan.FromSeconds(0.07 * i), Scheduler.Dispatcher)
                .Subscribe(e =>
                {
                    l.Left = e.EventArgs.X + closure * 12 - 5;
                    l.Top = e.EventArgs.Y + 15;
                });
            Controls.Add(l);
        }
    }
    

    注意 ObserveOnDispatcher 和 SubscribeOnDispatcher。这使我们接近了 Javascript 版本,但线程再次是这里的真正问题。

    更新,在上面的代码中添加了来自 Jeff Van Gogh 的更正


    只是为了好玩,这里是没有 Rx 的相同事物的模糊渲染:

    private void Unreactive(string msg)
    {
        var message = msg.ToCharArray();
    
        for(int i = 0; i < message.Length; i++)
        {
            var l = new Label()
            { 
                Text = message[i].ToString(), 
                AutoSize = true, 
                TextAlign = ContentAlignment.MiddleCenter 
            };
            Controls.Add(l);
            int closure = i;
            this.MouseMove += (s, e) => LabelDelayMove(closure, e, l);
        }
    }
    
    private void LabelDelayMove(int i, MouseEventArgs e, Label l)
    {
        Point p = new Point(e.X + i * 12 - 5, e.Y - 15);
        var timer = new System.Threading.Timer((_) => LabelMove(l, p), null, i * 70, System.Threading.Timeout.Infinite);
    }
    
    private void LabelMove(Label l, Point location)
    {
        this.BeginInvoke(new Action(() => l.Location = location));
    }
    

    【讨论】:

    • 链接到原帖?啊,我在你的问题中看到了,但不是这个答案。
    • @Richard,是的,我已经添加了问题的链接,但我一生都看不到答案的链接。他们真的应该放弃他们的论坛,来这里参加聚会!
    猜你喜欢
    • 1970-01-01
    • 2012-10-21
    • 2015-04-24
    • 2017-05-09
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多