gpt4 book ai didi

python - tkinter:停止文本小部件标签中的事件传播

转载 作者:太空狗 更新时间:2023-10-30 00:07:55 25 4
gpt4 key购买 nike

我目前正在编写配色方案编辑器。对于该方案的预览,我使用了一个文本小部件,我在其中插入带有相应颜色标签的文本(我以编程方式生成)。

我想要的是以下行为:

  • 单击文本小部件上没有文本的任意位置:更改背景颜色
  • 点击插入标签的文字:更改标签对应的前景色

现在这是我的问题:

当我点击标记的文本时,标记的回调被调用。到目前为止,一切都很好。但是,文本小部件的回调也会被调用,尽管我在标签回调方法中返回了“break”(这应该会停止进一步的事件处理)。 我怎样才能阻止它?

为了说明这个具体问题,我编写了这个工作示例(适用于 Python 2 和 3):

#!/usr/bin/env python

try:
from Tkinter import *
from tkMessageBox import showinfo
except ImportError:
from tkinter import *
from tkinter.messagebox import showinfo

def on_click(event, widget_origin='?'):
showinfo('Click', '"{}"" clicked'.format(widget_origin))
return 'break'

root = Tk()
text = Text(root)
text.pack()
text.insert(CURRENT, 'Some untagged text...\n')
text.bind('<Button-1>', lambda e, w='textwidget': on_click(e, w))
for i in range(5):
tag_name = 'tag_{}'.format(i)
text.tag_config(tag_name)
text.tag_bind(tag_name, '<Button-1>',
lambda e, w=tag_name: on_click(e, w))
text.insert(CURRENT, tag_name + ' ', tag_name)
root.mainloop()

感谢任何帮助!

编辑:也尝试过 Python 2。

最佳答案

感谢您提出这个问题并提供解决方案。我无法计算我花了多少时间来解决这种行为造成的症状。奇怪Tk设计决定tag_bindreturn "break"不敏感.

按照您的想法劫持 Text通过将小部件与与 tag_bind 相同的事件序列绑定(bind),我改进了解决方案,现在可以模拟预期的 return "break" Tk 的其他绑定(bind)+回调对的行为。想法如下(完整来源如下):

  1. 围绕希望的 callback 创建一个包装器,即一个可调用的类实例
  2. 调用类实例时,运行callback并检查其结果。
    • 如果结果是"break" ,暂时劫持事件传播:bind Text绑定(bind)到 tag_bind 的同一事件的小部件,带有一个空的回调。然后,在空闲时间后,unbind .
    • 如果结果不是"break" : 什么都不做,事件将传播到 Text自动

这是一个完整的工作示例。我的具体问题是获得某种超文本 行为:按住 Ctrl 键并单击超文本不应将插入点移动到单击位置。下面的示例显示在 tag_bind 中包含的同一回调中,我们可以将事件传播或不传播到 Text小部件,只需返回 "break"或其他值。

try:
# Python2
import Tkinter as tk
except ImportError:
# Python3
import tkinter as tk

class TagBindWrapper:
def __init__(self, sequence, callback):
self.callback=callback
self.sequence=sequence

def __call__(self, event):
if "break" == self.callback(event):
global text
self.bind_id=text.bind(self.sequence, self.break_tag_bind)
return "break"
else:
return

def break_tag_bind(self, event):
global text
# text.after(100, text.unbind(self.sequence, self.bind_id))
text.after_idle(text.unbind, self.sequence, self.bind_id)
return "break"



def callback_normal(event):
print "normal text clicked"
return "break"

def callback_hyper(event):
print "hyper text clicked"
if event.state & 0x004: # ctrl modifier
return "break" # will not be passed on to text widget
else:
return # will be passed on to text widget

# setup Text widget
root=tk.Tk()
text = tk.Text(root)
text.pack()
text.tag_config("normal", foreground="black")
text.tag_config("hyper", foreground="blue")
text.tag_bind("hyper", "<Button-1>", TagBindWrapper("<Button-1>", callback_hyper))
text.tag_bind("normal", "<Button-1>", callback_normal)

# write some normal text and some hyper text
text.insert(tk.END, "normal text, ", "normal")
text.insert(tk.END, "hyper text (try normal-click and ctrl-click).", "hyper")

root.mainloop()

有一个简化我找不到如何做:替换包装器调用 TagBindWrapper("<Button-1>", callback_hyper)通过 TagBindWrapper(callback_hyper) ,即仅从 "<Button-1>" 获取事件“序列”字符串 ( event) 的信息对象传递给 __call__ .可能吗?

关于python - tkinter:停止文本小部件标签中的事件传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13066773/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com