关于在 Tcl/Tk 中构建事件的新手问题

问题描述

如果您正在尝试构建具有半复杂 GUI 的桌面程序,尤其是其中用户可以打开相同 GUI 组件的多个实例的程序,例如具有“项目”GUI 并允许用户在其中同时打开多个项目主窗口,将事件侦听器进一步推到小部件层次结构并使用事件详细信息来确定事件发生在哪个小部件上,而不是将事件侦听器放置在每个单独的小部件上是否是一种好习惯?

例如,在 Web 浏览器中执行类似操作时,任何单个项目 GUI 元素上都没有事件侦听器。侦听器位于包含每个项目 GUI 的多个实例的父容器上。一个项目在其 GUI 中有多个选项卡,但在一个项目中一次只能看到一个选项卡,并且在任何时候都只能看到一个项目;因此,在 HTML 元素上使用类非常容易,然后在 e.matches() 上使用 event.target 方法以独立于哪个项目的方式对当前可见项目中的当前可见选项卡进行操作就是那是可见的。在没有任何真正的性能测试的情况下,我作为一个业余爱好者的不合格印象是,尽可能少的事件侦听器会更有效,而我通过阅读不太准确的信息获得了大部分。

我最近在 John Ousterhout 的书中读到 Tk 应用程序可以有数百个事件处理程序,并想知道尝试如上所述限制它们的数量是否真的会对 Tcl/Tk 产生任何影响。

我提出这个问题的目的仅仅是为了更好地理解事件,以便正确开始我的 Tcl/Tk 程序的编码,而不必重新编码一堆结构不良的事件侦听器。我不想对上述书中写的任何内容提出异议,如果我愿意,我也不知道这样做。

感谢您提供的任何指导。

解决方法

拥有数百个事件处理程序通常只是一个标志,表明可能会发送许多不同的事件。由于您通常(但并非总是)尝试将绑定专门化为尽可能具体,因此实际的事件处理程序通常非常小,但可能会调用一个过程来完成这项工作。这在实践中往往效果很好。我自己,我的经验法则是,如果它不是一个简单的调用,那么我将放入一个辅助程序;以这种方式调试它们会更容易。 (我的规则的主要例外是如果我想生成一个 break。)

您可以通常在四个级别bind(加上更多针对canvastext的小部件特定级别):

  1. 单个小部件。这是您最常使用的小部件。
  2. 小部件类。这主要由 Tk 使用;您通常不想想要更改它,因为它可能会改变您刚刚使用的代码的行为。 (例如,不要改变按钮的行为!)
  3. 包含小部件的顶层。这是热键的理想选择。 (不过要非常小心;这个级别的一些绑定可能会带来麻烦。<Destroy> 是通常会咬人的那个。)顶级小部件本身没有这个,因为规则 1。
  4. all,它按照它说的做,而且您几乎不需要。

您可以使用 bindtags 定义其他人……但这通常不是一个好的计划,因为它需要大量工作。

要记住的另一件事是 Tk 支持虚拟事件 <<FooBarHappened>>。它们有各种各样的用途,但在复杂应用程序中的主要用途(您应该注意)是用于定义偶尔由一系列低级事件触发的高级事件,以及除了原创者不妨留意一下。