Tk中的分层事件转发

Hierarchical event forwarding in Tk

假设我有以下 Widget 层次结构:

set Frame  [frame .f -relief flat]
set Button [button .f.b1]

此外,如果我想通过执行以下操作来模拟 button 小部件的 -overrelief

# When the mouse hovers over Frame
bind $Frame <Enter> "$Frame configure -relief groove"

# When it exits
bind $Frame <Leave> "$Frame configure -relief flat"

问题变成了 $Button 以某种方式打破了这个“传播链”,即 <Enter> 事件 而不是 达到$Frame。有补救措施还是这种固有的 Tk 行为?

编辑:

如果(鼠标)指针触及外边框然后触发 <Enter> 事件,则上述示例有效,但问题 仍然存在,以下对代码的修改最能说明这一点:

#When the pointer is inside the frame widget, print x,y (as relative to the widget)
bind .f <Motion> {puts {%x %y}}

puts 仅当指针位于框架的 edges 时才会被调用,不在框架内。

我无法重现您声称的问题。当我的鼠标指针进入按钮时(即使来自另一个 window,它部分覆盖了 Tk GUI,因此指针永远不会接触到框架),我在框架和按钮上都收到了一个 事件。

使用您的示例代码,浮雕变化不可见,因为框架的默认边框宽度为 0。因此您需要将边框宽度指定为 2 左右。

这是一个完整的脚本,可以满足您的需求:

set Frame  [frame .f -relief flat -borderwidth 2]
set Button [button .f.b1]
grid $Frame
grid $Button

# When the mouse hovers over Frame
bind $Frame <Enter> [list $Frame configure -relief groove]

# When it exits
bind $Frame <Leave> [list $Frame configure -relief flat]

事件确实没有报告给框架。如果您也希望发生这种情况,可以将框架添加到按钮的绑定标签中:

bindtags $Button [linsert [bindtags $Button] 1 $Frame]

这将使按钮上的任何事件也触发框架绑定,除非按钮绑定特别阻止。

有了这个,当直接进入按钮时,框架的 事件实际上触发了两次。一次是因为框架本身的事件,还有一次是因为按钮的绑定标签。