【问题标题】:How to make mouse events handling easier?如何使鼠标事件处理更容易?
【发布时间】:2012-01-16 02:40:16
【问题描述】:

有时我必须实现自定义拖放等功能。代码可能是这样的:

bool mouse_down = false;
Vec2 mouse_pos;
void on_mouse_down() {
  mouse_down = true;
  mouse_pos = cursor_pos();
}
void on_mouse_move() {
  if(mouse_down) {
    Vec2f c = cursor_pos();
    Vec2f d = c - mouse_pos;
    // dragging. make objects tracing the cursor.
    // ...
  }
}
void on_mouse_up() {
  mouse_down = false;
  // dropped
  // ...
}

我知道这很好用,但我根本不喜欢这样的冗余变量和分离程序。在 IP(命令式编程)中可能是不可避免的;我的问题是,有没有更好的方法来处理 FP(函数式编程)中的这种事情?无论是何种编程语言、Lisp、Scheme、F#、Ruby 等,还是在 IP 中执行此操作的更好方法,任何想法和建议都值得赞赏?

【问题讨论】:

  • 上面的代码只是一个最简单的示例。如果我在整个系统中添加更多的功能和限制,变量帐户会爆炸,比如左、右、中间、滚轮、双击、光标在不同对象上的不同操作......

标签: functional-programming imperative-programming


【解决方案1】:

由于一天没有人尝试回答,我会试一试。我了解您正在讨论的问题,但答案可能取决于操作系统、语言及其运行时库。

一般的想法是,当鼠标按下时,你会产生一个异步计算。这种计算“阻塞”事件,并在自己的循环中处理它们,做你需要做的事情;它在鼠标按钮向上时存在。虽然这个 看起来 像命令式线程一样工作,但实际上,当计算“阻塞”时,它只会控制它从哪里开始(调用鼠标按下事件的主 GUI 线程,想必)。通过这种方式,状态被封装到看起来像是计算的词法本地范围内。这种魔力必须由语言的运行时处理,所以这是我们能以一种语言和操作系统无关的方式得到的答案。

作为此类实现的示例,请查看 this answerarticle by Tomas Petricek,它们都在讨论您的问题,但在 Windows、.NET 和 F# 的狭窄设置中。同一位 Perticek 写了一本书,Real World Functional Programming: With Examples in F# and C#,令人惊讶的是,相同的想法在 C# 中表达,通常不被视为函数式语言。第16章,如果我没记错的话,就是你的了。

至于在 IP/OO 语言程序中封装状态,您可以在 mouse_down 处理程序中创建一个类的实例。该实例将向运行时注册自身以接收其他鼠标和 UI 事件、处理它们、完成所有工作,并在需要时(鼠标上升或窗口系统取消捕获模式)取消注册并自行销毁。不像函数式语言所允许的那样优雅,但仍然比在通用 UI 类中保持可变状态要好得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多