2

我有一个将鼠标事件分派到侦听器列表的方法。问题是,如果我只是使用

    [Obsolete]
    private void DispatchOld(MouseEvent e)
    {
        foreach (var listener in _listeners)
        {
            listener.OnMouse(e, _currentState);
        }
    }

然后,当我双击鼠标时,立即触发左键单击,然后双击。我正在努力做到这一点,如果我双击,那是唯一触发的事件,没有左键单击。所以本质上,如果检测到左键单击,我想推迟调度该事件,直到我知道下一步是否双击,否则只处理诸如中键单击、右键单击等事件,通常没有任何延迟或修改。使用我的新代码,这几乎可以工作,除了当我单击左键时,该事件不会触发,而是等待并触发双击。有人可以提出解决此问题的方法吗,我想检测单击左键和双击,但不检测左键,然后立即双击。所以 LRLRLDLLLD 应该是 LRLRDLLD。事件是一个Stack<MouseEvent>. 添加事件后,在 Update 循环中调用 Dispatch。

    private void Dispatch()
    {
        bool wait = false;

        foreach (var item in Events)
        {
            if (!wait)
            {
                if (item == MouseEvent.LeftClick) { wait = true; } // Delay the left click
                else
                {
                    foreach (var listener in _listeners)
                    {
                        listener.OnMouse(item, _currentState);
                    }
                }
            }
            else
            {
                if (item == MouseEvent.DoubleClick)
                {
                    foreach (var listener in _listeners)
                    {
                        listener.OnMouse(MouseEvent.DoubleClick, _currentState);
                    }
                }
                else
                {
                    foreach (var listener in _listeners)
                    {
                        listener.OnMouse(MouseEvent.LeftClick, _currentState); // The delayed event
                        listener.OnMouse(item, _currentState);
                    }
                }

                wait = false; // Delt with wait, continue as normal
            }             
        }

        Events.Clear();
    }

我想不出解决这个问题的方法,我的代码感觉混乱和重复,我可以重命名并使用 dispatchOld 来消除一些重复,但我想把所有东西都放在一个方法中。我的程序的另一部分正在触发事件流,该部分可以正常工作,检测事件并发送它们。


\\\\\\\\\\\\\\\\\\\\\\\ 已回答 \\\\\\\\\\\\\\\\\\\\\\\\\

编辑:我似乎已经使用System.Diagnostics.StopWatch().

使用 System.Diagnostics 中包含的秒表,我能够获得所需的行为

    private Stopwatch _delayTimer = new Stopwatch();

    private void Dispatch(MouseEvent e)
    {
        foreach (var listener in _listeners)
        {
            listener.OnMouse(e, _currentState);
        }
    }

    private void Dispatcher()
    {
        const long maxDelay = 200;

        foreach (var item in Events)
        {
            if (_delayTimer.IsRunning) // Running because Left trigger
            {
                if (item == MouseEvent.DoubleClick)
                {
                    _delayTimer.Reset();
                    Dispatch(MouseEvent.DoubleClick);
                    return; // Delt with
                }

                if (_delayTimer.ElapsedMilliseconds >= maxDelay) // Waited too long, must be a real left click
                {
                    _delayTimer.Reset();
                    Dispatch(MouseEvent.LeftClick);
                    Dispatch(item);
                    return; // Delt with
                }
            }
            else
            {
                if (item == MouseEvent.LeftClick) // Ignore and return, but start timer from zero
                {
                    _delayTimer.Restart();
                    return;
                }
                Dispatch(item);
            }
        }           
    }

它仍然有点乱,我将 Dispatch 重命名为 Dispatcher 并重命名 DispatchOld Dispatch。以免在Dispatcher方法中重复自己。我也开始意识到我可能不需要使用堆栈,因为每次在我的更新代码中检测到事件时,都会调用调度程序,因此永远不会有累积的堆栈。我正在优化代码。目前,上述作品如广告所示,我再次提出问题并亲自回答。

4

0 回答 0