如何使鼠标事件处理更容易?

时间:2012-01-16 02:40:16

标签: functional-programming imperative-programming

有时候我必须实现像自定义拖动和放大器这样的功能。下降。代码可能如下所示:

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中做一些更好的方法,我们都会对任何想法和建议表示赞赏?

1 个答案:

答案 0 :(得分:1)

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

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

至于这种实现的一个示例,请检查this answerarticle by Tomas Petricek,两者都讨论您的问题,但是在Windows,.NET和F#的狭窄设置中。有一本同一个Perticek的书,Real World Functional Programming: With Examples in F# and C#,在C#中表达了相同的想法,令人惊讶的是,它通常不被认为是一种功能语言。第十六章,如果我的记忆能为我服务,那就是你的。

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