Python实现高亮文本鼠标悬停弹出提示框的问题求助
Tkinter文本框高亮指定Token并实现悬停弹窗的解决方案
问题背景
需求:在Tkinter文本框中高亮指定的多个Token,鼠标悬停在高亮Token上时弹出提示对话框。
现有代码能高亮字符位置1.0到1.5的"token1",但鼠标悬停该高亮区域时无反应,而Label组件的悬停功能正常。
用户原有代码:
import tkinter as tk from tkinter import * class Example(tk.Frame): def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) self.l1 = tk.Label(self, text="Hover over me") self.l2 = tk.Label(self, text="", width=40) self.l1.pack(side="top") self.l2.pack(side="top", fill="x") self.inputText = tk.Text(root, height = 10, width = 70, bg = "light yellow") self.inputText.insert('1.0', "token1 token2 token3 etc.") self.inputText.pack() self.display_annotate = tk.Button(self, height = 2, width = 20, text ="Annotate text", command = lambda: self.add_highlighter()) self.display_annotate.place(x = 750, y = 20) print(self.__dict__.keys()) self.l1.bind("<Enter>", lambda event, text="text": self.on_enter(text=text)) self.l1.bind("<Leave>", self.on_leave) def take_input(self,): text_to_annotate = self.inputText.get("1.0", "end-1c") print(text_to_annotate) return text_to_annotate def on_enter(self, text): self.l2.configure(text=text) def on_leave(self, event): self.l2.configure(text="") def add_highlighter(self): self.inputText.tag_add("start", "1.0", "1.5") self.inputText.bind("<Enter>", lambda event, text="ali": self.on_enter(text=text)) self.inputText.tag_config("start", background= "black", foreground= "white") if __name__ == "__main__": root = tk.Tk() scrollb = tk.Scrollbar(root) scrollb.pack(side = tk.RIGHT, fill=tk.Y) var1 = tk.IntVar() var2 = tk.IntVar() root.geometry("900x500+10+10") root.title('Annotation page') Example(root).pack(side="top", fill="both", expand="true") root.mainloop()
问题原因
事件绑定对象错误:你给整个Text组件绑定了<Enter>事件,而非给高亮用的**tag(标签)**绑定。Text组件的全局<Enter>事件仅在鼠标进入整个文本框时触发,无法识别鼠标是否悬停在特定高亮区域。
解决方案
- 给高亮tag绑定
<Enter>和<Leave>事件,而非绑定到整个Text组件 - 优化Text组件的创建方式,改为作为Frame的子组件(避免依赖全局root变量)
- 支持多Token高亮,通过批量配置实现不同Token的独立提示
修改后的完整代码:
import tkinter as tk from tkinter import * class Example(tk.Frame): def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) self.l1 = tk.Label(self, text="Hover over me") self.l2 = tk.Label(self, text="", width=40, bg="#f0f0f0") self.l1.pack(side="top", pady=5) self.l2.pack(side="top", fill="x", padx=5, pady=2) # 将Text组件改为Frame的子组件,避免全局变量依赖 self.inputText = tk.Text(self, height=10, width=70, bg="light yellow") self.inputText.insert('1.0', "token1 token2 token3 etc.") self.inputText.pack(pady=5) self.display_annotate = tk.Button(self, height=2, width=20, text="Annotate text", command=self.add_highlighter) self.display_annotate.place(x=750, y=20) # Label的悬停绑定保留 self.l1.bind("<Enter>", lambda event, text="Label提示": self.on_enter(text)) self.l1.bind("<Leave>", self.on_leave) def take_input(self): text_to_annotate = self.inputText.get("1.0", "end-1c") print(text_to_annotate) return text_to_annotate def on_enter(self, text): self.l2.configure(text=text) def on_leave(self, event): self.l2.configure(text="") def add_highlighter(self): # 批量配置多个Token的高亮和提示 tokens_info = [ ("token1", "1.0", "1.6", "这是token1的提示"), ("token2", "1.7", "1.13", "这是token2的提示"), ("token3", "1.14", "1.20", "这是token3的提示") ] for token_name, start_idx, end_idx, tip_text in tokens_info: tag_name = f"highlight_{token_name}" # 添加tag并配置高亮样式 self.inputText.tag_add(tag_name, start_idx, end_idx) self.inputText.tag_config(tag_name, background="black", foreground="white") # 给当前tag绑定悬停事件 self.inputText.tag_bind(tag_name, "<Enter>", lambda e, t=tip_text: self.on_enter(t)) self.inputText.tag_bind(tag_name, "<Leave>", self.on_leave) if __name__ == "__main__": root = tk.Tk() scrollb = tk.Scrollbar(root) scrollb.pack(side=tk.RIGHT, fill=tk.Y) root.geometry("900x500+10+10") root.title('Annotation page') app = Example(root) app.pack(side="top", fill="both", expand=True) # 关联滚动条与文本框,修复原代码滚动无效问题 scrollb.config(command=app.inputText.yview) app.inputText.config(yscrollcommand=scrollb.set) root.mainloop()
关键修改说明
- Tag事件绑定:使用
self.inputText.tag_bind()替代全局Text组件绑定,确保仅当鼠标悬停在对应高亮区域时触发事件 - 多Token支持:通过
tokens_info列表批量处理多个Token,每个Token对应独立tag,可绑定不同提示文本 - 组件层级优化:将Text组件改为Frame的子组件,代码更规范,避免全局变量依赖
- 滚动条修复:补充滚动条与文本框的关联逻辑,解决原代码中滚动条无效的问题
内容的提问来源于stack exchange,提问作者bib
相关产品推荐
相关产品推荐

