tkinter 在绑定到 double_click 事件时出现意外行为 - 什么是双击?

tkinter behaves unexpectedly when binding to double_click event - what is a double click?

我将 tk 8.6 与 python 3.5 一起使用。

我正在编写一个应用程序,我需要对单击和双击都进行操作,有时双击可能会非常接近。

tk 文档指出,当您绑定到单击事件和双击事件时,第一次单击会生成 Button-1 事件,第二次单击会生成 Double-Button-1 事件。这是我双击一次时观察到的结果。

当我重复双击时,我希望看到以下事件 - 单次、双次、单次、双次。这是我在两次双击之间留下明显停顿时所看到的。当我一个接一个地快速重复时,我看到单、双、双、双。当我放慢操作速度时,看到一个或另一个的阈值大致是区分双击和两个单次的点击间延迟。

tkinter 似乎将任何紧随其后的点击视为双击。我原以为它会根据第一次点击是否是双击的第二次点击来限定第一次点击,如果是,则将 'third' 点击视为一次点击。此行为意味着由一对双击生成的事件序列会根据双击间延迟而变化。

为了获得一致的行为,我的解决方法是停止绑定到 double,为单打计时,并为双击设置我自己的延迟阈值。我认为这比试图解释双打是否 'really' 双击更清晰。

这种行为是 tkinter 中的错误吗?

其他 GUI 管理员在这种情况下会做什么?

是否有关于在这些情况下应该发生什么的定义?

/edit/ 我刚刚注意到 tk 也支持三次和四次点击。但是,我仍然认为 tk 的行为有些出乎意料。如果我只绑定到单击,那么我的 'two double clicks',基本上是四次单击,会生成四个单个事件。因此,我希望仅绑定到单次和双次,它应该将单击和双击的四重音解释为单次、双次、单次、双次。我想我最终的程序文档应该提到我不使用三次或四次点击。但是,嘿,我有我的解决方法。 //编辑/

/edit2/ 我不得不点击三次和四次以查看会发生什么,但它会出现更多错误。我从来没有通过四次单击获得四次事件。我确实收到了一系列单人、双人、三人、双人事件。我也有一个,双人,三人,三人,与 AFAICS 相同的输入时间。我会坚持只绑定单打,并按照自己的时间安排! //编辑2/

docs

The Double, Triple and Quadruple modifiers are a convenience for specifying double mouse clicks and other repeated events. They cause a particular event pattern to be repeated 2, 3 or 4 times, and also place a time and space requirement on the sequence: for a sequence of events to match a Double, Triple or Quadruple pattern, all of the events must occur close together in time and without substantial mouse motion in between. For example, <Double-Button-1> is equivalent to <Button-1><Button-1> with the extra time and space requirement.

-> 部分 Multiple matches

If more than one binding matches a particular event and they have the same tag, then the most specific binding is chosen and its script is evaluated. The following tests are applied, in order, to determine which of several matching sequences is more specific: 

(c) if the modifiers specified in one pattern are a subset of the modifiers in another pattern, then the pattern with more modifiers is more specific. 

所以这应该有效:

def func2(event):
    print('double')
    widget.unbind('<Double-1>')

def func1(event):
    print('single')
    widget.bind('<Double-1>', func2)

widget.bind('<Button-1>', func1)

编辑

成功了,试试:

import tkinter as tk

root = tk.Tk()

up = tk.Frame(root)
up.grid(column=0, row=0,columnspan=3,sticky='n')
s1 = tk.Label(up, text='spacer')
s1.pack(fill='both',expand=1)

def func4(event):
    print('Quadruple')
    s1.unbind('<Quadruple-1>')

def func3(event):
    print('triple')
    s1.unbind('<Triple-1>')
    s1.bind('<Quadruple-1>', func4)

def func2(event):
    print('double')
    s1.unbind('<Double-1>')
    s1.bind('<Triple-1>', func3)
    

def func1(event):
    print('single')
    s1.bind('<Double-1>', func2)

s1.bind('<Button-1>', func1)

root.mainloop()

在 Atlas435 的带领下,我现在有了另一种方法来实现问题中要求的 'two double clicks'。我的解决方法涉及仅绑定到单个事件并手动为它们计时,这有点不纯,因为它复制了通过 OS 设置的 double-click 计时设置。 DRY的分布式案例。

我不确定动态绑定和取消绑定是否真的是我想要的,但它很简单,而且确实有效。它很好地表达了我想要的,即“当上一次点击是第二次点击时不响应双击”。

import tkinter as tki

root = tki.Tk()

s1 = tki.Label(root, text='click here', width=15, height=3)
s1.pack()

def func2(event):
    print('double')
    s1.unbind('<Double-1>')   

def func1(event):
    print('single')
    s1.bind('<Double-1>', func2)

s1.bind('<Button-1>', func1)

root.mainloop()