禁用 tkinter 键盘快捷键 (2)

发布于 2024-11-26 06:23:56 字数 1325 浏览 1 评论 0原文

我建议继续禁用 tkinter 键盘快捷键中的讨论:我有一个事件处理程序对于 Tkinter 也使用的事件,以便我的 prog & Tkinter 交互很糟糕。

因为这是一个我一直无法解决的问题,所以我在这里重新提出,我试图在以下代码中将其归结为最简单的形式:

#!/usr/bin/env python

from Tkinter import *
import tkFont

def init():
    global root,text

    root = Tk()
    root.geometry("500x500+0+0")
    dFont=tkFont.Font(family="Arial", size=10)

    text=Text(root, width=16, height=5, font=dFont)
    text.pack(side=LEFT, fill=BOTH, expand = YES)

    root.bind("<Control-b>", setbold)

    text.tag_config("b",font=('Verdana', '10', 'bold' ))
    text.tag_config("i",font=('Verdana', '10', 'italic' ))

def removeformat(event=None):
    text.tag_remove('b',SEL_FIRST,SEL_LAST)
    text.tag_remove('i',SEL_FIRST,SEL_LAST)

def setbold(event=None):
    removeformat()
    text.tag_add('b', SEL_FIRST,SEL_LAST)
    text.edit_modified(True)

def main():
    init()        
    mainloop()


if __name__ == '__main__':
    main()

它应该做的只是生成一个文本窗口,您可以在其中输入写入. 选择一些文本并按 Ctrl+B 程序应删除任何先前存在的标记,然后为其分配将文本设置为粗体的“b”标记。

相反,在第一个 tag_remove 处发生异常,告诉我 text 不包含任何用“sel”标记的字符

使用 return 'break' 的建议是没有用的,因为选择在 setbold() 有机会执行之前就消失了......

I'm proposing a continuation of the discussion in disable tkinter keyboard shortcut: I have an event handler for an event that Tkinter also uses, so that my prog & Tkinter interact badly.

Since it is a problem that I've been unable to solve I'm re-proposing here, where I tried to boil it down to the simplest form in the following code:

#!/usr/bin/env python

from Tkinter import *
import tkFont

def init():
    global root,text

    root = Tk()
    root.geometry("500x500+0+0")
    dFont=tkFont.Font(family="Arial", size=10)

    text=Text(root, width=16, height=5, font=dFont)
    text.pack(side=LEFT, fill=BOTH, expand = YES)

    root.bind("<Control-b>", setbold)

    text.tag_config("b",font=('Verdana', '10', 'bold' ))
    text.tag_config("i",font=('Verdana', '10', 'italic' ))

def removeformat(event=None):
    text.tag_remove('b',SEL_FIRST,SEL_LAST)
    text.tag_remove('i',SEL_FIRST,SEL_LAST)

def setbold(event=None):
    removeformat()
    text.tag_add('b', SEL_FIRST,SEL_LAST)
    text.edit_modified(True)

def main():
    init()        
    mainloop()


if __name__ == '__main__':
    main()

What it should do is simply to produce a text window where you write into.
Selecting some text and pressing Ctrl+B the program should remove any preexisting tag, then assign to it the 'b' tag that sets the text to bold.

What instead happens is an exception at the first tag_remove, telling me that text doesn't contain any characters tagged with "sel".

The suggestion to use a return 'break' is of no use, since the selection disappears before setbold() has any chance to act...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

又怨 2024-12-03 06:23:56

在文本小部件上设置绑定,而不是在根上。 (整个顶级绑定小部件类绑定之后处理 - 标准 绑定所在的位置 - 并且这些之后处理> 小部件实例绑定,这就是您要在此处使用的内容。)并且您需要执行此操作 'break';它抑制后续的结合。 (如果此后遇到任何问题,可能是默认情况下焦点错误,但这很容易修复。)

唯一的其他选择是重新配置绑定标签,以便在顶级绑定之后处理类绑定,但后果这样做是非常微妙和深远的;您应该使用我第一段中的更简单的方法,因为这是处理这些事情的正常方法。

Set your binding on the text widget, not on the root. (Whole toplevel bindings are processed after widget class bindings – where the standard <Control-Key-b> binding is – and those are processed after the widget instance bindings, which is what you want to use here.) And you need to do that 'break'; it inhibits the subsequent bindings. (If you're having any problems after that, it's probably that the focus is wrong by default, but that's easy to fix.)

The only other alternative is to reconfigure the bindtags so that class bindings are processed after toplevel bindings, but the consequences of doing that are very subtle and far-reaching; you should use the simpler approach from my first paragraph instead as that's the normal way of handling these things.

源来凯始玺欢你 2024-12-03 06:23:56

绑定按特定顺序处理,由该小部件的 bindtags 定义。默认情况下,这个顺序是:

  1. 特定的小部件
  2. 小部件类
  3. 顶层窗口
  4. 特殊类“all”

如果存在冲突的绑定 - 例如,小部件和类上的 control-b 绑定 - 它们都会触发(在所描述的顺序),除非您通过返回“break”来破坏链。

然而,在您发布的代码的情况下,您绑定到顶级窗口(即:根窗口),并且冲突的绑定位于类上。因此,绑定将在类被顶层处理之前触发,因此即使您的绑定返回 "break" 也没关系,因为类绑定首先发生。

最直接的解决方案是将绑定移动到实际的小部件并返回“break”。这将保证您的绑定首先触发,并且返回“break”保证类绑定不会触发。

如果您确实希望在根窗口上进行绑定,则可以使用 bind_class 方法以及该类的 "Text" 值来删除该类的绑定。

您可能会在 effbot 上找到事件和绑定页面。组织变得有用。

Bindings are handled in a specific order, defined by the bindtags of that widget. By default this order is:

  1. The specific widget
  2. The widget class
  3. The toplevel window
  4. The special class "all"

If there are conflicting bindings -- for example, a control-b binding on both the widget and class -- they both will fire (in the described order) unless you break the chain by returning "break".

In the case of the code you posted, however, you are binding to the toplevel window (ie: the root window), and the conflicting binding is on the class. Therefore, the binding will fire for the class before it is processed by the toplevel, so even if your binding returned "break" it wouldn't matter since the class binding happens first.

The most straight-forward solution is to move your binding to the actual widget and return "break". That will guarantee your binding fires first, and the return "break" guarantees that the class binding does not fire.

If you really want your binding on the root window, you can remove the binding for the class using the bind_class method with the value of "Text" for the class.

You might find the Events and Bindings page on effbot.org to be useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文