【问题标题】:Is it possible to alter binding order of a Tk/Tkinter Listbox widget <<ListboxSelect>> event是否可以更改 Tk/Tkinter 列表框小部件 <<ListboxSelect>> 事件的绑定顺序
【发布时间】:2021-05-09 14:51:37
【问题描述】:

据我了解,Tk/Tkinter Listbox 小部件的“正常”绑定事件顺序是(简化):&lt;ButtonPress&gt;, &lt;&lt;ListboxSelect&gt;&gt;, &lt;ButtonRelease&gt;

是否可以“更改”顺序以便在&lt;ButtonRelease&gt; 之后触发&lt;&lt;ListboxSelect&gt;&gt; 事件?

为此,我尝试使用bindtags 和自定义“假”bind_class,但到目前为止还没有得到想要的结果...... 这是代码示例:

import tkinter as tk

root = tk.Tk()

l = tk.Listbox(root, name='custlist')
for e in range(55): l.insert(tk.END, 'L_item'+str(e))
l.pack()

l.bind('<ButtonPress>', lambda e: print("L: Click"))
l.bind('<ButtonRelease>', lambda e: print("L: ButtonRelease"))

l.bind_class("post-class-bindings", "<<ListboxSelect>>", lambda e: print("L: post-ListboxSelect"))
l.bindtags((l.winfo_pathname(l.winfo_id()),'Listbox','post-class-bindings', '.', 'all'))

你能告诉我是否有可能以这种或另一种方式获得这样的东西? 谢谢

编辑:

想到它,我意识到我不能那样做,因为我猜 &lt;ButtonPress&gt;+&lt;&lt;ListboxSelect&gt;&gt; 事件在其流程中有些“链接”,而 &lt;ButtonRelease&gt; 是“未绑定”的,因此我应该在 &lt;ButtonRelease&gt; 回调结束时调用/生成 &lt;&lt;ListboxSelect&gt;&gt; 事件以触发它......可能在大多数情况下都可以工作,但是...这不是我想要达到的目的...(实际上,这就像将&lt;&lt;ListboxSelect&gt;&gt; 事件代码“移动”到&lt;ButtonRelease&gt; callbak ...) 所以,最后,问题是是否可以将 ButtonRelease 与 ListboxSelect 一起“链接”(与 ButtonPress 相同)? ...我想这样的事情是不可能的

【问题讨论】:

    标签: python python-3.x tkinter tk


    【解决方案1】:

    是否可以“更改”订单以便在订单之后触发&lt;&lt;ListboxSelect&gt;&gt; 事件?

    这样做的唯一方法是防止在单击按钮时更改选择。 &lt;&lt;ListboxSelect&gt;&gt; 不是按钮单击或按钮释放的直接结果,而是选择已更改的直接结果。您不能在单击时更改选择并且不会生成&lt;&lt;ListboxSelect&gt;&gt;

    我不太明白您的真正需求是什么,但是如果您想在按钮释放时收到选择更改的通知,您可以随时在&lt;ButtonRelease-1&gt; 的处理程序中发出您自己的自定义虚拟事件,例如例如,&lt;&lt;ListboxSelectAfterClick&gt;&gt;

    【讨论】:

    • 嗨 Bryan,现在这主要是出于好奇,因为 99% 的时间我都设法“解决”了这些问题,而无需更改绑定顺序之类的东西。剩下的 1% 的情况下,只有当列表选择模式设置为“单一”时,我才觉得需要这样的东西……但是,即使那样,我通常也可以简单地最终将列表选择模式“恢复”为默认值,而不需要这个导致或产生其余代码的剧变。感谢您对此的澄清(您的帮助像往常一样宝贵),从他们开始,我现在可以发布答案......
    • P.S.还有一个问题,我错了,还是它在&lt;ButtonRelease-1&gt;(例如&lt;&lt;ListboxSelectAfterClick&gt;&gt;)的处理程序中发出自定义虚拟事件就像直接在&lt;ButtonRelease-1&gt;回调中添加代码一样?跨度>
    【解决方案2】:

    感谢 Bryan Oakley 的澄清,我找到了一个可能的解决方案:

    我的主要目的是拥有该元素 只有在释放鼠标按钮后才能激活/触发列表中的选择。

    import tkinter as tk
    
    root = tk.Tk()
    
    l = tk.Listbox(temp, name='custlist', selectmode='single')
    for e in range(55): l.insert(tk.END, 'L_item'+str(e))
    l.pack()
    
    l.bind('<ButtonPress>', lambda e: "break")
    def AfterReleaseSelect(event):
        event.widget.selection_clear(0,tk.END)
        event.widget.selection_set(event.widget.nearest(event.y))
        #more stuffs here if needed...
    l.bind('<ButtonRelease>', AfterReleaseSelect)
    

    实际上,我在这里所做的是阻止按钮单击完成其工作,以便不会触发列表框选择,然后等待释放鼠标按钮来完成工作。

    对此的一些最终想法:

    首先,请注意:我在这里向列表框小部件添加了selectmode='single' 参数,因为我认为在处理默认(“'browse'-select”)列表框时应用这种方法是不值得的。这是因为,与“'browse'-select”列表框不同,使用“'single'-select”列表框元素选择不会“跟随”鼠标直到最后,它会在第一次单击时“卡住”-元素,即使您结束在不同项目上释放鼠标按钮。

    我必须说,无论如何,这可能在大多数时候都不值得,因为你可能只是:

    • 避免使用selectmode='single'参数,保留默认列表框'browse'-select-behavior;
    • “移动”您将使用绑定&lt;&lt;ListboxSelect&gt;&gt; 执行的代码到&lt;ButtonRelease&gt; 上的绑定(只要这不涉及对其余代码的太多“扭曲”,当然... )

    【讨论】:

      猜你喜欢
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      • 2020-06-05
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      相关资源
      最近更新 更多