-
Notifications
You must be signed in to change notification settings - Fork 2
/
tooltip.py
137 lines (116 loc) · 4.08 KB
/
tooltip.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
""" tk_ToolTip_class101.py
gives a Tkinter widget a tooltip as the mouse is above the widget
tested with Python27 and Python34 by vegaseat 09sep2014
www.daniweb.com/programming/software-development/code/484591/a-tooltip-class-for-tkinter
Modified to include a delay time by Victor Zaccardo, 25mar16
"""
try:
# for Python2
import Tkinter as tk
except ImportError:
# for Python3
import tkinter as tk
class CreateToolTip(object):
"""
create a tooltip for a given widget
"""
def __init__(self, widget, text='widget info'):
self.waittime = 500 #miliseconds
self.wraplength = 180 #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 = 0
x, y, cx, cy = self.widget.bbox("insert")
x += self.widget.winfo_rootx() + 25
y += self.widget.winfo_rooty() + 20
# creates a toplevel window
self.tw = tk.Toplevel(self.widget)
# Leaves only the label and removes the app window
self.tw.wm_overrideredirect(True)
self.tw.wm_geometry("+%d+%d" % (x, y))
label = tk.Label(self.tw, text=self.text, justify='left',
background="#ffffff", relief='solid', borderwidth=1,
wraplength = self.wraplength)
label.pack(ipadx=1)
def hidetip(self):
tw = self.tw
self.tw= None
if tw:
tw.destroy()
"""
Top-Level menu with tooltips
Created by StackOverflow user stovfl
Available online at https://stackoverflow.com/questions/55316791/how-can-i-add-a-tooltip-to-menu-item
It doesn't seem to work...
"""
class MenuTooltip(tk.Menu):
def __init__(self, parent):
"""
:param parent: The parent of this Menu, either 'root' or 'Menubar'
.tooltip == List of tuple (yposition, text)
.tooltip_active == Index (0-based) of the active shown Tooltip
Bind events <Leave>, <Motion>
"""
super().__init__(parent, tearoff=0)
self.tooltip = []
self.tooltip_active = None
self.bind('<Leave>', self.leave)
self.bind('<Motion>', self.on_motion)
def add_command(self, *cnf, **kwargs):
tooltip = kwargs.get('tooltip')
if tooltip:
del kwargs['tooltip']
super().add_command(*cnf, **kwargs)
self.add_tooltip(len(self.tooltip), tooltip)
def add_tooltip(self, index, tooltip):
"""
:param index: Index (0-based) of the Menu Item
:param tooltip: Text to show as Tooltip
:return: None
"""
self.tooltip.append((self.yposition(index) + 2, tooltip))
def on_motion(self, event):
"""
Loop .tooltip to find matching Menu Item
"""
for idx in range(len(self.tooltip) - 1, -1, -1):
if event.y >= self.tooltip[idx][0]:
self.show_tooltip(idx)
break
def leave(self, event):
"""
On leave, destroy the Tooltip and reset .tooltip_active to None
"""
if not self.tooltip_active is None:
print('leave()'.format())
# destroy(<tooltip_active>)
self.tooltip_active = None
def show_tooltip(self, idx):
"""
Show the Tooltip if not already shown, destroy the active Tooltip
:param idx: Index of the Tooltip to show
:return: None
"""
if self.tooltip_active != idx:
# destroy(<tooltip_active>)
self.tooltip_active = idx
print('{}'.format(self.tooltip[idx][1]))