【问题标题】:Reuse an existing standard binding for a different key combination为不同的组合键重用现有的标准绑定
【发布时间】:2018-02-25 14:44:57
【问题描述】:

我想指定一个组合键来执行与现有标准绑定相同的操作。

具体来说,对于 tkinter.Listbox,使 Ctrl-A 全选 (same as Ctrl-/) 并对 Ctrl+<the keys corresponding to those two in my national keyboard layout> 执行相同操作。

由于执行此操作的子例程存在于 Tk 级别而不是 Python 级别,因此我不能像对 Python 函数那样只对它们.bind()

【问题讨论】:

  • 您的问题包括一些陈述,但没有提出问题。另外,使用现有绑定真的很重要,还是创建自己的“全选”功能就足够了?
  • @BryanOakley 重新实现将是一个较差的解决方案。尽管明显没有问号,但您似乎已经理解了问题所在。
  • 重新实现是微不足道的。这是几行代码。
  • 我似乎理解这个问题的事实是无关紧要的。显然我的猜测很幸运。标题询问如何重用现有绑定(一般而言),但正文似乎在询问如何具体实现“全选”功能。目前尚不清楚您需要帮助解决什么问题。你真的需要学习如何重用任何现有的标准绑定,只重用列表框的“全选”绑定,还是简单地让“”做与“全选”相同的事情。
  • @BryanOakley “我想指定一个组合键来完成与现有标准绑定相同的操作。” 以手头的具体问题为例,以便答案可能具有与我的案例更相关的代码,并且可能包含该特定案例的其他详细信息(如果有的话)。仅适用于“Ctrl-A for “全选”的特定情况的解决方案太没用了,不值得专门询问。

标签: python tkinter tk key-bindings


【解决方案1】:

如果您想复制任何现有绑定,您需要做的第一件事是了解原始序列绑定到什么。在这种情况下,绑定<Control-/> 绑定到绑定标签“Listbox”(内部小部件类的名称)

第一步是通过对 Tcl 解释器进行原始调用来获取现有绑定:

func = root.call("bind", "Listbox", "<Control-/>")

第二步是将原始功能与新的组合键相关联:

root.call("bind", "Listbox", "<Control-A>", func)

注意:以上将绑定与所有列表框小部件相关联,而不仅仅是特定列表框。

【讨论】:

  • 无需原始调用也可实现:root.call("bind",...) -> root.bind_class(...)
【解决方案2】:

您可以从源代码中找到 用于特定绑定的命令。


对于 Listbox 的具体情况,Control-/ 事件首先激活一个虚拟事件,&lt;&lt;SelectAll&gt;&gt;。然后调用列表框的 Tcl 过程 tk::ListboxSelectAll 的 Tcl 命令。

让我们指定 Control-A 来模仿 Control-/

生成&lt;&lt;SelectAll&gt;&gt; 事件,以便它调用它应该调用的任何东西:

lb.bind('<Control-Key-a>', lambda event: lb.event_generate('<<SelectAll>>'))

或者你可以直接调用&lt;&lt;SelectAll&gt;&gt;最终调用的对象:

lb.bind('<Control-Key-a>', lambda event: lb.tk.call('tk::ListboxSelectAll', lb))

您可能希望为 所有 列表框对象绑定:

lb.bind_class(lb.winfo_class(), '<Control-Key-a>',
                    lambda event: lb.tk.call('tk::ListboxSelectAll', lb))

一个完整的例子:

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


if __name__ == '__main__':
    root = tk.Tk()
    lb = tk.Listbox(root)
    for i in range(4):
        lb.insert('end', i)
    lb.bind_class(lb.winfo_class(), '<Control-Key-a>',
                        lambda event: lb.tk.call('tk::ListboxSelectAll', lb))
    # assign anything but "single" or "browse"
    # so that the effect is obvious
    lb['selectmode'] = 'asd'
    lb.pack()
    tk.mainloop()

最后,请注意,您可能还想绑定到 &lt;Control-Key-A&gt;,因此即使打开 Caps Lock 也可以进行绑定。

这也将有效地绑定Ctrl-Shift-A,您可能想要也可能不想要。相反,在 Caps Lock 开启的情况下,Tk 会将Ctrl-Shift-A 解释为Ctrl-A

【讨论】:

  • 我将选择lb.event_generate('&lt;&lt;SelectAll&gt;&gt;'),因为它做出的假设最少。谢谢。
  • 嗯,lb.event_generate('&lt;&lt;SelectAll&gt;&gt;') 没有效果。因此不得不接受 Bryan 的建议,尽管它做了一个不必要的假设(默认绑定没有重新定义)。
  • @ivan_pozdeev 我故意将其保留为大写字母,以指出如果需要此类功能,则需要同时绑定小写和大写字母。
  • 用大写字母绑定有什么意义?我不需要绑定Ctrl-Shift-A。如果还有其他隐藏的原因,您应该明确说明。
  • @ivan_pozdeev 原因是 ctrl-a 选择所有带或不带大写锁定的字符串。
【解决方案3】:

我自己问过very similar question

您可以简单地生成您想要模仿的事件。


生成 Control-/ 事件,以便它处理从那时起的所有内容:

lb.bind('<Control-Key-a>',
                    lambda event:lb.event_generate('<Control-Key-slash>'))

一个完整的例子:

try:                        # In order to be able to import tkinter for
    import tkinter as tk    # either in python 2 or in python 3
except ImportError:
    import Tkinter as tk


if __name__ == '__main__':
    root = tk.Tk()
    lb = tk.Listbox(root)
    for i in range(4):
        lb.insert('end', i)

    lb.bind('<Control-Key-a>',
                    lambda event:lb.event_generate('<Control-Key-slash>'))
    # assign anything but "single" or "browse"
    # so that the effect is obvious
    lb['selectmode'] = 'asd'
    lb.pack()
    tk.mainloop()

【讨论】:

  • 这个答案和你的另一个答案完全一样,除了一个陈述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2016-10-27
相关资源
最近更新 更多