An easy and customisable ToolTip implementation for Tkinter
npx @tessl/cli install tessl/pypi-tkinter-tooltip@3.1.0A 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.
pip install tkinter-tooltipfrom tktooltip import ToolTip, ToolTipStatus, __version__Alternative import:
import tktooltip
tooltip = tktooltip.ToolTip(widget, msg="Hello")
print(f"Using tktooltip version: {tktooltip.__version__}")import tkinter as tk
import tkinter.ttk as ttk
from tktooltip import ToolTip
# Create main window
app = tk.Tk()
# Create a button widget
button = ttk.Button(app, text="Hover over me!")
button.pack(padx=20, pady=20)
# Add simple tooltip
ToolTip(button, msg="This is a simple tooltip")
# Run the application
app.mainloop()The ToolTip implementation follows a clean architecture:
tk.Toplevel, providing the pop-up window functionalityCreates a simple tooltip that appears when hovering over a widget.
class ToolTip(tk.Toplevel):
def __init__(
self,
widget: tk.Widget,
msg: str | list[str] | Callable[[], str | list[str]],
delay: float = 0.0,
follow: bool = True,
refresh: float = 1.0,
x_offset: int = +10,
y_offset: int = +10,
parent_kwargs: dict | None = None,
**message_kwargs: Any,
):
"""
Create a ToolTip for a tkinter widget.
Parameters:
- widget: The tkinter widget to attach the tooltip to
- msg: Tooltip message (string, list of strings, or callable returning them)
- delay: Delay in seconds before tooltip appears (default: 0.0)
- follow: Whether tooltip follows mouse cursor (default: True)
- refresh: Refresh rate for dynamic content in seconds (default: 1.0)
- x_offset: X-coordinate offset for tooltip positioning (default: +10)
- y_offset: Y-coordinate offset for tooltip positioning (default: +10)
- parent_kwargs: Optional styling kwargs for parent frame
- **message_kwargs: Additional tkinter styling kwargs for tooltip message
"""Usage example:
import tkinter as tk
from tktooltip import ToolTip
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
# Basic tooltip
ToolTip(entry, msg="Enter your text here")
root.mainloop()Control when tooltips appear using the delay parameter.
# delay parameter controls appearance timing
ToolTip(widget, msg="Delayed tooltip", delay=2.0)Usage example:
import tkinter as tk
from tktooltip import ToolTip
root = tk.Tk()
button = tk.Button(root, text="Hover and wait")
button.pack()
# Tooltip appears after 2 seconds
ToolTip(button, msg="This appeared after a 2 second delay", delay=2.0)
root.mainloop()Configure whether tooltips follow the mouse cursor.
# follow parameter controls mouse tracking behavior
ToolTip(widget, msg="Tracking tooltip", follow=True) # Default
ToolTip(widget, msg="Static tooltip", follow=False)Usage example:
import tkinter as tk
from tktooltip import ToolTip
root = tk.Tk()
label1 = tk.Label(root, text="Follows mouse")
label2 = tk.Label(root, text="Stays in place")
label1.pack()
label2.pack()
# Tooltip follows mouse movement
ToolTip(label1, msg="I follow your cursor!", follow=True)
# Tooltip stays at initial position
ToolTip(label2, msg="I stay put", follow=False)
root.mainloop()Use functions to create tooltips with dynamic, updating content.
# msg parameter accepts callable functions
ToolTip(widget, msg=callable_function, refresh=1.0)Usage example:
import time
import tkinter as tk
from tktooltip import ToolTip
def current_time():
return f"Current time: {time.strftime('%H:%M:%S')}"
root = tk.Tk()
clock_label = tk.Label(root, text="Hover for time")
clock_label.pack()
# Dynamic tooltip showing current time, updates every 0.5 seconds
ToolTip(clock_label, msg=current_time, refresh=0.5)
root.mainloop()Display multi-line content using lists of strings.
# msg parameter accepts list of strings
ToolTip(widget, msg=["Line 1", "Line 2", "Line 3"])Usage example:
import tkinter as tk
from tktooltip import ToolTip
root = tk.Tk()
info_button = tk.Button(root, text="Information")
info_button.pack()
# Multi-line tooltip
ToolTip(info_button, msg=[
"Application Info:",
"Version: 1.0",
"Author: Developer",
"License: MIT"
])
root.mainloop()Fully customize tooltip appearance with tkinter styling options.
# Styling through parent_kwargs and message_kwargs
ToolTip(
widget,
msg="Styled tooltip",
parent_kwargs={"bg": "black", "padx": 5, "pady": 5},
fg="white",
bg="black",
font=("Arial", 12)
)Usage example:
import tkinter as tk
from tktooltip import ToolTip
root = tk.Tk()
styled_button = tk.Button(root, text="Styled tooltip")
styled_button.pack()
# Custom styled tooltip
ToolTip(
styled_button,
msg="Custom styled tooltip",
parent_kwargs={"bg": "#2E2E2E", "padx": 8, "pady": 6},
fg="#FFFFFF",
bg="#2E2E2E",
font=("Consolas", 11, "bold"),
justify="center"
)
root.mainloop()Manage tooltip lifecycle and check status.
class ToolTip:
def destroy(self) -> None:
"""Destroy the tooltip and unbind all events."""
def on_enter(self, event: tk.Event) -> None:
"""Handle mouse enter events."""
def on_leave(self, event: tk.Event | None = None) -> None:
"""Handle mouse leave events."""
# Properties
status: ToolTipStatus # Current tooltip status
widget: tk.Widget # Reference to attached widget
msg: str | list[str] | Callable # Tooltip message contentUsage example:
import tkinter as tk
from tktooltip import ToolTip, ToolTipStatus
root = tk.Tk()
button = tk.Button(root, text="Manageable tooltip")
button.pack()
# Create tooltip with reference
tooltip = ToolTip(button, msg="I can be managed")
# Check tooltip status
def check_status():
print(f"Tooltip status: {tooltip.status}")
root.after(1000, check_status) # Check every second
check_status()
# Destroy tooltip when needed
def destroy_tooltip():
tooltip.destroy()
print("Tooltip destroyed")
destroy_button = tk.Button(root, text="Destroy tooltip", command=destroy_tooltip)
destroy_button.pack()
root.mainloop()Access the package version programmatically.
__version__: str # Package version stringUsage example:
from tktooltip import __version__
print(f"tktooltip version: {__version__}")from enum import Enum, auto
from typing import Any, Callable
import tkinter as tk
# Version export
__version__: str
class ToolTipStatus(Enum):
"""Enumeration for tooltip status states."""
OUTSIDE = auto() # Mouse cursor is outside the widget
INSIDE = auto() # Mouse cursor is inside widget but tooltip not visible
VISIBLE = auto() # Tooltip is currently visible
class ToolTip(tk.Toplevel):
"""
Creates a ToolTip (pop-up) widget for tkinter.
Attributes:
- widget: tk.Widget - Reference to the attached widget
- msg: str | list[str] | Callable - The tooltip message content
- delay: float - Delay before tooltip appears
- follow: bool - Whether tooltip follows mouse
- refresh: float - Refresh rate for dynamic content
- x_offset: int - X-coordinate offset
- y_offset: int - Y-coordinate offset
- status: ToolTipStatus - Current tooltip status
- msg_var: tk.StringVar - StringVar for message display
- message_widget: tk.Message - Message widget hosting content
"""
# Class constants
DEFAULT_PARENT_KWARGS: dict = {"bg": "black", "padx": 1, "pady": 1}
DEFAULT_MESSAGE_KWARGS: dict = {"aspect": 1000}
S_TO_MS: int = 1000 # Seconds to milliseconds conversionThe ToolTip class includes proper error handling:
msg parameter is not a string, list of strings, or callable returning them# This will raise TypeError
try:
ToolTip(widget, msg=123) # Invalid message type
except TypeError as e:
print(f"Error: {e}")
# Proper error handling example
def safe_tooltip_creation(widget, message):
try:
return ToolTip(widget, msg=message)
except TypeError:
print("Invalid message type provided")
return None