[英]Python tkinter: stopping event propagation in text widgets tags
我正在寫一個配色方案編輯器。 對於方案的預覽,我使用文本小部件,其中我插入帶有相應顏色標簽的文本(我以編程方式生成)。
我想要的是以下行為:
現在這是我的問題:
當我單擊標記文本時,將調用標記的回調。 到現在為止還挺好。 但是,也調用了文本小部件的回調,盡管我在標簽回調方法中返回“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。
好吧,在
tkint稍微
修補一下后,我能夠找到一個有效的解決方案。 我認為問題是標簽可能不是BaseWidget的子類。
我的解決方法:
代碼中的解決方法(抱歉在這里使用global
,但我只修改了我的問題簡單示例...):
#!/usr/bin/env python
try:
from Tkinter import *
from tkMessageBox import showinfo
except ImportError:
from tkinter import *
from tkinter.messagebox import showinfo
tag_to_handle = ''
def on_click(event, widget_origin='?'):
global tag_to_handle
if tag_to_handle:
showinfo('Click', '"{}" clicked'.format(tag_to_handle))
tag_to_handle = ''
else:
showinfo('Click', '"{} " clicked'.format(widget_origin))
def on_tag_click(event, tag):
global tag_to_handle
tag_to_handle = tag
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_tag_click(e, w))
text.insert(CURRENT, tag_name + ' ', tag_name)
root.mainloop()
我希望這對有同樣問題的人有幫助。
當然,我仍然願意接受更好的解決方案!
感謝您發布此問題並提供解決方案。 我無法計算我試圖修復這種行為造成的症狀的時間。 奇怪Tk
是設計決定tag_bind
是insenstive到return "break"
。
通過將其與tag_bind
相同的事件序列綁定來劫持Text
小部件,我已經改進了解決方案, 現在可以模擬Tk的其他綁定+回調對的預期return "break"
行為 。 這個想法如下(完整的來源如下):
callback
周圍創建一個包裝器,即一個可調用的類實例 callback
並檢查其結果。
"break"
,則暫時劫持事件傳播: bind
Text
小部件綁定到綁定到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(callback_hyper)
替換包裝器調用TagBindWrapper("<Button-1>", callback_hyper)
TagBindWrapper(callback_hyper)
,即獲取事件'sequence'字符串的信息( "<Button-1>"
)簡單地從傳遞給__call__
的event
對象。 可能嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.