0
# Tkinter Tooltip
1
2
A comprehensive and fully customizable tooltip implementation specifically designed for tkinter widgets. It offers advanced features including delayed tooltips with configurable timing, mouse cursor tracking capabilities, support for both static strings and dynamic function-based content with refresh control, and complete theme integration for both light and dark tkinter themes.
3
4
## Package Information
5
6
- **Package Name**: tkinter-tooltip (install name)
7
- **Import Name**: tktooltip (import name)
8
- **Language**: Python
9
- **Installation**: `pip install tkinter-tooltip`
10
11
## Core Imports
12
13
```python
14
from tktooltip import ToolTip, ToolTipStatus, __version__
15
```
16
17
Alternative import:
18
19
```python
20
import tktooltip
21
tooltip = tktooltip.ToolTip(widget, msg="Hello")
22
print(f"Using tktooltip version: {tktooltip.__version__}")
23
```
24
25
## Basic Usage
26
27
```python
28
import tkinter as tk
29
import tkinter.ttk as ttk
30
from tktooltip import ToolTip
31
32
# Create main window
33
app = tk.Tk()
34
35
# Create a button widget
36
button = ttk.Button(app, text="Hover over me!")
37
button.pack(padx=20, pady=20)
38
39
# Add simple tooltip
40
ToolTip(button, msg="This is a simple tooltip")
41
42
# Run the application
43
app.mainloop()
44
```
45
46
## Architecture
47
48
The ToolTip implementation follows a clean architecture:
49
50
- **ToolTip**: Main tooltip class inheriting from `tk.Toplevel`, providing the pop-up window functionality
51
- **ToolTipStatus**: Enum tracking tooltip state (OUTSIDE, INSIDE, VISIBLE)
52
- **Binding**: Internal helper class managing widget event bindings for automatic tooltip behavior
53
- **Event-driven**: Automatic mouse event handling (enter, leave, motion, button press) for seamless user experience
54
55
## Capabilities
56
57
### Basic Tooltip Creation
58
59
Creates a simple tooltip that appears when hovering over a widget.
60
61
```python { .api }
62
class ToolTip(tk.Toplevel):
63
def __init__(
64
self,
65
widget: tk.Widget,
66
msg: str | list[str] | Callable[[], str | list[str]],
67
delay: float = 0.0,
68
follow: bool = True,
69
refresh: float = 1.0,
70
x_offset: int = +10,
71
y_offset: int = +10,
72
parent_kwargs: dict | None = None,
73
**message_kwargs: Any,
74
):
75
"""
76
Create a ToolTip for a tkinter widget.
77
78
Parameters:
79
- widget: The tkinter widget to attach the tooltip to
80
- msg: Tooltip message (string, list of strings, or callable returning them)
81
- delay: Delay in seconds before tooltip appears (default: 0.0)
82
- follow: Whether tooltip follows mouse cursor (default: True)
83
- refresh: Refresh rate for dynamic content in seconds (default: 1.0)
84
- x_offset: X-coordinate offset for tooltip positioning (default: +10)
85
- y_offset: Y-coordinate offset for tooltip positioning (default: +10)
86
- parent_kwargs: Optional styling kwargs for parent frame
87
- **message_kwargs: Additional tkinter styling kwargs for tooltip message
88
"""
89
```
90
91
Usage example:
92
```python
93
import tkinter as tk
94
from tktooltip import ToolTip
95
96
root = tk.Tk()
97
entry = tk.Entry(root)
98
entry.pack()
99
100
# Basic tooltip
101
ToolTip(entry, msg="Enter your text here")
102
103
root.mainloop()
104
```
105
106
### Delayed Tooltips
107
108
Control when tooltips appear using the delay parameter.
109
110
```python { .api }
111
# delay parameter controls appearance timing
112
ToolTip(widget, msg="Delayed tooltip", delay=2.0)
113
```
114
115
Usage example:
116
```python
117
import tkinter as tk
118
from tktooltip import ToolTip
119
120
root = tk.Tk()
121
button = tk.Button(root, text="Hover and wait")
122
button.pack()
123
124
# Tooltip appears after 2 seconds
125
ToolTip(button, msg="This appeared after a 2 second delay", delay=2.0)
126
127
root.mainloop()
128
```
129
130
### Mouse Tracking Tooltips
131
132
Configure whether tooltips follow the mouse cursor.
133
134
```python { .api }
135
# follow parameter controls mouse tracking behavior
136
ToolTip(widget, msg="Tracking tooltip", follow=True) # Default
137
ToolTip(widget, msg="Static tooltip", follow=False)
138
```
139
140
Usage example:
141
```python
142
import tkinter as tk
143
from tktooltip import ToolTip
144
145
root = tk.Tk()
146
label1 = tk.Label(root, text="Follows mouse")
147
label2 = tk.Label(root, text="Stays in place")
148
label1.pack()
149
label2.pack()
150
151
# Tooltip follows mouse movement
152
ToolTip(label1, msg="I follow your cursor!", follow=True)
153
154
# Tooltip stays at initial position
155
ToolTip(label2, msg="I stay put", follow=False)
156
157
root.mainloop()
158
```
159
160
### Dynamic Content Tooltips
161
162
Use functions to create tooltips with dynamic, updating content.
163
164
```python { .api }
165
# msg parameter accepts callable functions
166
ToolTip(widget, msg=callable_function, refresh=1.0)
167
```
168
169
Usage example:
170
```python
171
import time
172
import tkinter as tk
173
from tktooltip import ToolTip
174
175
def current_time():
176
return f"Current time: {time.strftime('%H:%M:%S')}"
177
178
root = tk.Tk()
179
clock_label = tk.Label(root, text="Hover for time")
180
clock_label.pack()
181
182
# Dynamic tooltip showing current time, updates every 0.5 seconds
183
ToolTip(clock_label, msg=current_time, refresh=0.5)
184
185
root.mainloop()
186
```
187
188
### Multi-line Tooltips
189
190
Display multi-line content using lists of strings.
191
192
```python { .api }
193
# msg parameter accepts list of strings
194
ToolTip(widget, msg=["Line 1", "Line 2", "Line 3"])
195
```
196
197
Usage example:
198
```python
199
import tkinter as tk
200
from tktooltip import ToolTip
201
202
root = tk.Tk()
203
info_button = tk.Button(root, text="Information")
204
info_button.pack()
205
206
# Multi-line tooltip
207
ToolTip(info_button, msg=[
208
"Application Info:",
209
"Version: 1.0",
210
"Author: Developer",
211
"License: MIT"
212
])
213
214
root.mainloop()
215
```
216
217
### Custom Styling and Theming
218
219
Fully customize tooltip appearance with tkinter styling options.
220
221
```python { .api }
222
# Styling through parent_kwargs and message_kwargs
223
ToolTip(
224
widget,
225
msg="Styled tooltip",
226
parent_kwargs={"bg": "black", "padx": 5, "pady": 5},
227
fg="white",
228
bg="black",
229
font=("Arial", 12)
230
)
231
```
232
233
Usage example:
234
```python
235
import tkinter as tk
236
from tktooltip import ToolTip
237
238
root = tk.Tk()
239
styled_button = tk.Button(root, text="Styled tooltip")
240
styled_button.pack()
241
242
# Custom styled tooltip
243
ToolTip(
244
styled_button,
245
msg="Custom styled tooltip",
246
parent_kwargs={"bg": "#2E2E2E", "padx": 8, "pady": 6},
247
fg="#FFFFFF",
248
bg="#2E2E2E",
249
font=("Consolas", 11, "bold"),
250
justify="center"
251
)
252
253
root.mainloop()
254
```
255
256
### Tooltip Management
257
258
Manage tooltip lifecycle and check status.
259
260
```python { .api }
261
class ToolTip:
262
def destroy(self) -> None:
263
"""Destroy the tooltip and unbind all events."""
264
265
def on_enter(self, event: tk.Event) -> None:
266
"""Handle mouse enter events."""
267
268
def on_leave(self, event: tk.Event | None = None) -> None:
269
"""Handle mouse leave events."""
270
271
# Properties
272
status: ToolTipStatus # Current tooltip status
273
widget: tk.Widget # Reference to attached widget
274
msg: str | list[str] | Callable # Tooltip message content
275
```
276
277
Usage example:
278
```python
279
import tkinter as tk
280
from tktooltip import ToolTip, ToolTipStatus
281
282
root = tk.Tk()
283
button = tk.Button(root, text="Manageable tooltip")
284
button.pack()
285
286
# Create tooltip with reference
287
tooltip = ToolTip(button, msg="I can be managed")
288
289
# Check tooltip status
290
def check_status():
291
print(f"Tooltip status: {tooltip.status}")
292
root.after(1000, check_status) # Check every second
293
294
check_status()
295
296
# Destroy tooltip when needed
297
def destroy_tooltip():
298
tooltip.destroy()
299
print("Tooltip destroyed")
300
301
destroy_button = tk.Button(root, text="Destroy tooltip", command=destroy_tooltip)
302
destroy_button.pack()
303
304
root.mainloop()
305
```
306
307
### Version Information
308
309
Access the package version programmatically.
310
311
```python { .api }
312
__version__: str # Package version string
313
```
314
315
Usage example:
316
```python
317
from tktooltip import __version__
318
print(f"tktooltip version: {__version__}")
319
```
320
321
## Types
322
323
```python { .api }
324
from enum import Enum, auto
325
from typing import Any, Callable
326
import tkinter as tk
327
328
# Version export
329
__version__: str
330
331
class ToolTipStatus(Enum):
332
"""Enumeration for tooltip status states."""
333
OUTSIDE = auto() # Mouse cursor is outside the widget
334
INSIDE = auto() # Mouse cursor is inside widget but tooltip not visible
335
VISIBLE = auto() # Tooltip is currently visible
336
337
class ToolTip(tk.Toplevel):
338
"""
339
Creates a ToolTip (pop-up) widget for tkinter.
340
341
Attributes:
342
- widget: tk.Widget - Reference to the attached widget
343
- msg: str | list[str] | Callable - The tooltip message content
344
- delay: float - Delay before tooltip appears
345
- follow: bool - Whether tooltip follows mouse
346
- refresh: float - Refresh rate for dynamic content
347
- x_offset: int - X-coordinate offset
348
- y_offset: int - Y-coordinate offset
349
- status: ToolTipStatus - Current tooltip status
350
- msg_var: tk.StringVar - StringVar for message display
351
- message_widget: tk.Message - Message widget hosting content
352
"""
353
354
# Class constants
355
DEFAULT_PARENT_KWARGS: dict = {"bg": "black", "padx": 1, "pady": 1}
356
DEFAULT_MESSAGE_KWARGS: dict = {"aspect": 1000}
357
S_TO_MS: int = 1000 # Seconds to milliseconds conversion
358
```
359
360
## Error Handling
361
362
The ToolTip class includes proper error handling:
363
364
- **TypeError**: Raised when `msg` parameter is not a string, list of strings, or callable returning them
365
- **tk.TclError**: Handled gracefully during widget destruction using contextlib.suppress
366
- **Automatic cleanup**: Event bindings are automatically managed and cleaned up on destruction
367
368
```python
369
# This will raise TypeError
370
try:
371
ToolTip(widget, msg=123) # Invalid message type
372
except TypeError as e:
373
print(f"Error: {e}")
374
375
# Proper error handling example
376
def safe_tooltip_creation(widget, message):
377
try:
378
return ToolTip(widget, msg=message)
379
except TypeError:
380
print("Invalid message type provided")
381
return None
382
```