禁用 tkinter 键盘快捷键 (2)
我建议继续禁用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在文本小部件上设置绑定,而不是在根上。 (整个顶级绑定在小部件类绑定之后处理 - 标准
绑定所在的位置 - 并且这些在之后处理> 小部件实例绑定,这就是您要在此处使用的内容。)并且您需要执行此操作'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.
绑定按特定顺序处理,由该小部件的
bindtags
定义。默认情况下,这个顺序是:如果存在冲突的绑定 - 例如,小部件和类上的 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: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 thereturn "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.