You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>事件仅在鼠标进入整个文本框时触发,无法识别鼠标是否悬停在特定高亮区域。

解决方案

  1. 给高亮tag绑定<Enter>和<Leave>事件,而非绑定到整个Text组件
  2. 优化Text组件的创建方式,改为作为Frame的子组件(避免依赖全局root变量)
  3. 支持多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:45:36