我有一个带有 CheckboxTreeview 小部件的 Python 工具。树视图中的某些内容太长而无法显示。如果是这种情况,我想向用户提供工具提示。我的工具中其他地方已经有工具提示,但我无法将工具提示设置为 CheckboxTreeview 中的各个内容。你知道有什么办法吗?这怎么可能?
下面是一个最小的示例,我想在其中提供工具提示以供参考
ref2
。这怎么可能?
import tkinter as tk
from tkinter import ttk
from ttkwidgets import CheckboxTreeview
class CreateToolTip(object):
def __init__(self, widget, text='tooltip text', wraplength=180):
self.waittime = 400 #miliseconds
self.bg = '#fdfde3'
self.wraplength = wraplength #pixels
self.widget = widget
self.text = text
self.widget.bind("<Enter>", self.enter)
self.widget.bind("<Leave>", self.leave)
self.widget.bind("<ButtonPress>", self.leave)
self.id = None
self.tw = None
def enter(self, event=None):
self.schedule()
def leave(self, event=None):
self.unschedule()
self.hidetip()
def schedule(self):
self.unschedule()
self.id = self.widget.after(self.waittime, self.showtip)
def unschedule(self):
id = self.id
self.id = None
if id:
self.widget.after_cancel(id)
def showtip(self, event=None):
x, y, cx, cy = self.widget.bbox("insert")
self.tw = tk.Toplevel(self.widget)
self.tw.wm_overrideredirect(True)
tk.Label(self.tw, text=self.text, justify='left',background=self.bg,
relief='solid', borderwidth=1,wraplength = self.wraplength
).pack(ipadx=10)
x += self.widget.winfo_rootx()
y += self.widget.winfo_rooty()
self.tw.wm_geometry("+%d+%d" % (x, y))
def hidetip(self):
tw = self.tw
self.tw= None
if tw:
tw.destroy()
class App():
def __init__(self, master):
self.master = master
self.master.geometry('300x400')
self.master.columnconfigure(0, weight=1)
self.tree = CheckboxTreeview(self.master)
xsb = ttk.Scrollbar(self.master, orient='horizontal', command=self.tree.xview)
ysb = ttk.Scrollbar(self.master, orient='vertical', command=self.tree.yview)
self.tree.configure(yscroll=ysb.set)
self.tree['columns']=('x', 'y')
self.tree.column('x', anchor='e', width=40)
self.tree.column('y', width=40)
self.tree.heading('#0', text='abc', anchor='w')
self.tree.heading('x', text='x', anchor='w')
self.tree.heading('y', text='y', anchor='w')
self.tree.grid(row=0, column=0)
ysb.grid(row=0, column=1, sticky='ns')
xsb.grid(row=1, column=0, sticky='ew')
self.master.frame = tk.Frame(self.master, highlightbackground="black", highlightthickness=2)
self.master.frame.grid(row=4, column=0, columnspan=2, sticky='w')
ref = tk.Label(self.master.frame, text='TEXT', font=tk.font.Font(size=16, weight='bold'))
ref.grid(row=0, column=0)
CreateToolTip(ref, text='tooltip')
ref1 = self.tree.insert('', 'end', text='node 1', values=('x1', 'y1'), open=True)
ref2 = self.tree.insert('', 'end', text='node 2 - this is a very long text where a tooltip should be displayed', values=('x2', 'y2'), open=True)
root = tk.Tk()
app = App(root)
app.master.mainloop()
您需要删除对“插入”bbox 的依赖并将工具提示行为直接绑定到树项。试试这个方法:
class CreateToolTip(object):
def __init__(self, widget, text='tooltip text', wraplength=180):
self.waittime = 400 # milliseconds
self.hidetime = 2000
self.wraplength = wraplength #pixels
self.widget = widget
self.text = text
self.widget.bind("<Enter>", self.enter)
self.widget.bind("<Leave>", self.leave)
self.widget.bind("<ButtonPress>", self.leave)
self.id = None
self.tw = None
self.hide_id = None # new timer for auto-hide
def enter(self, event=None):
self.schedule()
def leave(self, event=None):
self.unschedule()
self.schedule_hide()
def schedule_hide(self):
if self.hide_id:
self.widget.after_cancel(self.hide_id)
self.hide_id = self.widget.after(self.hidetime, self.hidetip)
def schedule(self):
self.unschedule()
self.id = self.widget.after(self.waittime, self.showtip)
def unschedule(self):
if self.id:
self.widget.after_cancel(self.id)
self.id = None
def unschedule(self):
if self.id:
self.widget.after_cancel(self.id)
self.id = None
if self.hide_id:
self.widget.after_cancel(self.hide_id)
self.hide_id = None
def showtip(self, event=None):
x = self.widget.winfo_rootx() + self.widget.winfo_width()//2
y = self.widget.winfo_rooty()
self.hidetip()
self.tw = tk.Toplevel(self.widget)
self.tw.wm_overrideredirect(True)
label = tk.Label(self.tw, text=self.text, justify='left',
background="#ffffe0", relief='solid', borderwidth=1,
wraplength=self.wraplength)
label.pack()
self.tw.wm_geometry(f"+{x}+{y}")
self.schedule_hide()
def hidetip(self):
if self.tw:
self.tw.destroy()
self.tw = None
class App():
def __init__(self, master):
self.master = master
self.master.geometry('300x400')
self.master.columnconfigure(0, weight=1)
self.tree = CheckboxTreeview(self.master)
xsb = ttk.Scrollbar(self.master, orient='horizontal', command=self.tree.xview)
ysb = ttk.Scrollbar(self.master, orient='vertical', command=self.tree.yview)
self.tree.configure(yscroll=ysb.set)
self.tree['columns']=('x', 'y')
self.tree.column('x', anchor='e', width=40)
self.tree.column('y', width=40)
self.tree.heading('#0', text='abc', anchor='w')
self.tree.heading('x', text='x', anchor='w')
self.tree.heading('y', text='y', anchor='w')
self.tree.grid(row=0, column=0)
ysb.grid(row=0, column=1, sticky='ns')
xsb.grid(row=1, column=0, sticky='ew')
self.tree.bind('<Motion>', self.show_tree_tooltip)
self.current_tooltip = None
self.master.frame = tk.Frame(self.master, highlightbackground="black", highlightthickness=2)
self.master.frame.grid(row=4, column=0, columnspan=2, sticky='w')
ref = tk.Label(self.master.frame, text='TEXT', font=tk.font.Font(size=16, weight='bold'))
ref.grid(row=0, column=0)
CreateToolTip(ref, text='This is a ToolTip!!!')
ref1 = self.tree.insert('', 'end', text='node 1', values=('x1', 'y1'), open=True)
ref2 = self.tree.insert('', 'end',
text='node 2 - this is a very long text where a tooltip should be displayed',
values=('x2', 'y2'),
open=True)
self.tooltips = {
ref1: "Tooltip for node 1",
ref2: "node 2 - this is a very long text where a tooltip should be displayed"
}
def show_tree_tooltip(self, event):
item = self.tree.identify_row(event.y)
if not item:
if self.current_tooltip:
self.current_tooltip.leave()
return
if item in self.tooltips:
if self.current_tooltip and self.current_tooltip.text != self.tooltips[item]:
self.current_tooltip.hidetip()
self.current_tooltip = None
if not self.current_tooltip:
self.current_tooltip = CreateToolTip(self.tree, text=self.tooltips[item], wraplength=200)
self.current_tooltip.showtip()
else:
if self.current_tooltip:
self.current_tooltip.leave()
self.current_tooltip = None
root = tk.Tk()
app = App(root)
app.master.mainloop()
这样,每个项目就有单独的工具提示。我还添加了一个“计时器”来隐藏工具提示。你需要进一步调整它,因为我的工作间隔现在刚刚结束,哈哈。
希望这有帮助!干杯!