Elysia Tools

Browse tools, examples, visual explainers, and topic guides from one clear workspace.

Top Categories

Hubs

Language
ZHESPTRUFRDEEN

Elysia Tools

Navigation

Python

Web Python Desktop Features Samples

Web Python desktop GUI examples including file dialogs, message boxes, and system tray functionality using tkinter

Samples

Entries inside this sample collection

CodepythonIntermediate

File Dialogs

Open and save file dialogs, directory selection, and file information using tkinter.filedialog

Difficulty

5/10

Estimated time

30 min

Tags

python, web, desktop, gui, file-dialog

Prerequisites

Intermediate Python, tkinter module

python
# Web Python File Dialogs Examples
# File open/save dialogs using tkinter.filedialog
#
# NOTE: These are desktop GUI features that require a desktop environment
# Install tkinter (usually included with Python):
#   - Windows/Linux: Typically included with Python
#   - macOS: brew install python-tk
#
# Run with: python file_dialogs_examples.py

import tkinter as tk
from tkinter import filedialog, messagebox
from typing import Optional, List, Tuple
import os
from pathlib import Path

# 1. Open Single File Dialog
def open_single_file_dialog(
    title: str = "Open File",
    filetypes: Optional[List[Tuple[str, str]]] = None,
    initialdir: Optional[str] = None
) -> Optional[str]:
    """
    Open a dialog to select a single file

    Args:
        title: Dialog title
        filetypes: List of file type filters, e.g., [("Text files", "*.txt"), ("All files", "*.*")]
        initialdir: Initial directory to open

    Returns:
        Selected file path or None if cancelled
    """
    root = tk.Tk()
    root.withdraw()  # Hide the main window

    if filetypes is None:
        filetypes = [("All files", "*.*")]

    file_path = filedialog.askopenfilename(
        title=title,
        filetypes=filetypes,
        initialdir=initialdir
    )

    root.destroy()
    return file_path if file_path else None

# 2. Open Multiple Files Dialog
def open_multiple_files_dialog(
    title: str = "Open Files",
    filetypes: Optional[List[Tuple[str, str]]] = None,
    initialdir: Optional[str] = None
) -> List[str]:
    """
    Open a dialog to select multiple files

    Args:
        title: Dialog title
        filetypes: List of file type filters
        initialdir: Initial directory to open

    Returns:
        List of selected file paths or empty list if cancelled
    """
    root = tk.Tk()
    root.withdraw()

    if filetypes is None:
        filetypes = [("All files", "*.*")]

    file_paths = filedialog.askopenfilenames(
        title=title,
        filetypes=filetypes,
        initialdir=initialdir
    )

    root.destroy()
    return list(file_paths) if file_paths else []

# 3. Save File Dialog
def save_file_dialog(
    title: str = "Save File",
    defaultextension: str = "",
    filetypes: Optional[List[Tuple[str, str]]] = None,
    initialdir: Optional[str] = None,
    initialfile: Optional[str] = None
) -> Optional[str]:
    """
    Open a dialog to save a file

    Args:
        title: Dialog title
        defaultextension: Default extension to add if none provided
        filetypes: List of file type filters
        initialdir: Initial directory to open
        initialfile: Suggested filename

    Returns:
        Selected file path or None if cancelled
    """
    root = tk.Tk()
    root.withdraw()

    if filetypes is None:
        filetypes = [("All files", "*.*")]

    file_path = filedialog.asksaveasfilename(
        title=title,
        defaultextension=defaultextension,
        filetypes=filetypes,
        initialdir=initialdir,
        initialfile=initialfile
    )

    root.destroy()
    return file_path if file_path else None

# 4. Select Directory Dialog
def select_directory_dialog(
    title: str = "Select Directory",
    initialdir: Optional[str] = None,
    mustexist: bool = True
) -> Optional[str]:
    """
    Open a dialog to select a directory

    Args:
        title: Dialog title
        initialdir: Initial directory to open
        mustexist: Whether the directory must exist

    Returns:
        Selected directory path or None if cancelled
    """
    root = tk.Tk()
    root.withdraw()

    directory = filedialog.askdirectory(
        title=title,
        initialdir=initialdir,
        mustexist=mustexist
    )

    root.destroy()
    return directory if directory else None

# 5. Custom File Filter
def create_common_file_filters() -> dict:
    """
    Create common file type filters

    Returns:
        Dictionary of file type filters
    """
    return {
        'text': [("Text files", "*.txt"), ("All files", "*.*")],
        'image': [("Image files", "*.png *.jpg *.jpeg *.gif *.bmp"), ("All files", "*.*")],
        'document': [("Documents", "*.pdf *.doc *.docx *.txt"), ("All files", "*.*")],
        'python': [("Python files", "*.py"), ("All files", "*.*")],
        'json': [("JSON files", "*.json"), ("All files", "*.*")],
        'csv': [("CSV files", "*.csv"), ("All files", "*.*")],
        'all': [("All files", "*.*")]
    }

# 6. File Information
def get_file_info(file_path: str) -> dict:
    """
    Get information about a file

    Args:
        file_path: Path to the file

    Returns:
        Dictionary with file information
    """
    try:
        path = Path(file_path)
        stat_info = path.stat()

        return {
            'name': path.name,
            'stem': path.stem,
            'suffix': path.suffix,
            'parent': str(path.parent),
            'size': stat_info.st_size,
            'size_human': format_file_size(stat_info.st_size),
            'created': stat_info.st_ctime,
            'modified': stat_info.st_mtime,
            'is_file': path.is_file(),
            'is_dir': path.is_dir(),
            'exists': path.exists(),
            'absolute': str(path.absolute())
        }
    except Exception as e:
        return {'error': str(e)}

def format_file_size(size_bytes: int) -> str:
    """
    Format file size in human-readable format

    Args:
        size_bytes: Size in bytes

    Returns:
        Formatted size string
    """
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.2f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.2f} PB"

# 7. Batch File Operations
def batch_open_files(max_files: int = 10) -> List[str]:
    """
    Open multiple files with a limit

    Args:
        max_files: Maximum number of files to select

    Returns:
        List of selected file paths
    """
    root = tk.Tk()
    root.withdraw()

    file_paths = filedialog.askopenfilenames(title=f"Select up to {max_files} files")

    root.destroy()

    if file_paths:
        paths = list(file_paths)
        if len(paths) > max_files:
            messagebox.showwarning(
                "Too Many Files",
                f"You selected {len(paths)} files. Only the first {max_files} will be used."
            )
            return paths[:max_files]
        return paths

    return []

# 8. File Dialog with Preview
def open_file_with_validation(
    allowed_extensions: List[str],
    min_size: int = 0,
    max_size: int = 1024 * 1024 * 100  # 100 MB
) -> Optional[str]:
    """
    Open file dialog with validation

    Args:
        allowed_extensions: List of allowed extensions (e.g., ['.txt', '.py'])
        min_size: Minimum file size in bytes
        max_size: Maximum file size in bytes

    Returns:
        Validated file path or None
    """
    file_path = open_single_file_dialog()

    if not file_path:
        return None

    # Validate extension
    file_ext = Path(file_path).suffix.lower()
    if allowed_extensions and file_ext not in [ext.lower() for ext in allowed_extensions]:
        messagebox.showerror(
            "Invalid File Type",
            f"File must be one of: {', '.join(allowed_extensions)}"
        )
        return None

    # Validate size
    file_size = Path(file_path).stat().st_size
    if file_size < min_size or file_size > max_size:
        messagebox.showerror(
            "Invalid File Size",
            f"File size must be between {min_size} and {max_size} bytes"
        )
        return None

    return file_path

# 9. Recent Files Dialog
class RecentFilesManager:
    """Manager for recent files"""

    def __init__(self, max_files: int = 10):
        """
        Initialize recent files manager

        Args:
            max_files: Maximum number of recent files to track
        """
        self.max_files = max_files
        self.recent_files: List[str] = []

    def add_file(self, file_path: str) -> None:
        """
        Add a file to recent files

        Args:
            file_path: Path to add
        """
        if file_path in self.recent_files:
            self.recent_files.remove(file_path)

        self.recent_files.insert(0, file_path)

        if len(self.recent_files) > self.max_files:
            self.recent_files = self.recent_files[:self.max_files]

    def get_recent_files(self) -> List[str]:
        """Get list of recent files"""
        return self.recent_files.copy()

    def clear_recent(self) -> None:
        """Clear recent files list"""
        self.recent_files.clear()

# 10. Advanced File Dialog
def advanced_file_dialog(
    mode: str = 'open',
    filters: Optional[List[Tuple[str, str]]] = None,
    initial_dir: Optional[str] = None,
    initial_file: Optional[str] = None
) -> Optional[str]:
    """
    Advanced file dialog with multiple modes

    Args:
        mode: Dialog mode ('open', 'save', 'directory')
        filters: File type filters
        initial_dir: Initial directory
        initial_file: Initial filename (for save mode)

    Returns:
        Selected path or None
    """
    root = tk.Tk()
    root.withdraw()

    if filters is None:
        filters = [("All files", "*.*")]

    result = None

    if mode == 'open':
        result = filedialog.askopenfilename(
            title="Open File",
            filetypes=filters,
            initialdir=initial_dir
        )
    elif mode == 'save':
        result = filedialog.asksaveasfilename(
            title="Save File",
            filetypes=filters,
            initialdir=initial_dir,
            initialfile=initial_file
        )
    elif mode == 'directory':
        result = filedialog.askdirectory(
            title="Select Directory",
            initialdir=initial_dir
        )

    root.destroy()
    return result if result else None

# Usage Examples
def demonstrate_file_dialogs():
    """Demonstrate all file dialog examples"""
    print("=== Python File Dialogs Examples ===\n")

    # 1. Open single file
    print("--- 1. Open Single File Dialog ---")
    print("Opening file selection dialog...")
    # file = open_single_file_dialog(title="Select a Text File", filetypes=[("Text files", "*.txt")])
    # print(f"Selected: {file}")

    # 2. Open multiple files
    print("\n--- 2. Open Multiple Files Dialog ---")
    print("Opening multiple file selection dialog...")
    # files = open_multiple_files_dialog(title="Select Files")
    # print(f"Selected {len(files)} files")

    # 3. Save file
    print("\n--- 3. Save File Dialog ---")
    print("Opening save file dialog...")
    # saved = save_file_dialog(title="Save As", defaultextension=".txt")
    # print(f"Save to: {saved}")

    # 4. Select directory
    print("\n--- 4. Select Directory Dialog ---")
    print("Opening directory selection dialog...")
    # directory = select_directory_dialog(title="Select Working Directory")
    # print(f"Selected: {directory}")

    # 5. Custom filters
    print("\n--- 5. Custom File Filters ---")
    filters = create_common_file_filters()
    print(f"Available filter types: {list(filters.keys())}")

    # 6. File info
    print("\n--- 6. File Information ---")
    # if file:
    #     info = get_file_info(file)
    #     print(f"File info: {info}")

    # 7. Batch operations
    print("\n--- 7. Batch File Operations ---")
    print("Can select multiple files with limits")

    # 8. Validation
    print("\n--- 8. File Validation ---")
    print("Validates file type and size")

    # 9. Recent files
    print("\n--- 9. Recent Files Manager ---")
    recent = RecentFilesManager()
    recent.add_file("/path/to/file1.txt")
    recent.add_file("/path/to/file2.py")
    print(f"Recent files: {recent.get_recent_files()}")

    # 10. Advanced dialog
    print("\n--- 10. Advanced File Dialog ---")
    print("Multi-mode dialog: open, save, directory")

    print("\n=== All File Dialog Examples Completed ===")
    print("\nNOTE: Uncomment the dialog calls to see them in action")
    print("GUI dialogs require a desktop environment")

# Export functions
# export { open_single_file_dialog, open_multiple_files_dialog }
# export { save_file_dialog, select_directory_dialog }
# export { create_common_file_filters, get_file_info, format_file_size }
# export { batch_open_files, open_file_with_validation }
# export { RecentFilesManager, advanced_file_dialog }
# export { demonstrate_file_dialogs }
CodepythonSimple

Message Boxes

Display various message boxes including info, warning, error, and question dialogs using tkinter.messagebox

Difficulty

3/10

Estimated time

20 min

Tags

python, web, desktop, gui, message-box

Prerequisites

Basic Python, tkinter module

python
# Web Python Message Boxes Examples
# Message and dialog boxes using tkinter.messagebox
#
# NOTE: These are desktop GUI features that require a desktop environment
# Install tkinter (usually included with Python):
#   - Windows/Linux: Typically included with Python
#   - macOS: brew install python-tk
#
# Run with: python message_boxes_examples.py

import tkinter as tk
from tkinter import messagebox, simpledialog
from typing import Optional, Any

# 1. Information Message Box
def show_info(
    title: str = "Information",
    message: str = "Operation completed successfully!",
    parent: Optional[tk.Tk] = None
) -> None:
    """
    Show an information message box

    Args:
        title: Dialog title
        message: Message text
        parent: Parent window (None creates new root)
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        messagebox.showinfo(title, message)
        root.destroy()
    else:
        messagebox.showinfo(title, message, parent=parent)

# 2. Warning Message Box
def show_warning(
    title: str = "Warning",
    message: str = "Please be careful!",
    parent: Optional[tk.Tk] = None
) -> None:
    """
    Show a warning message box

    Args:
        title: Dialog title
        message: Message text
        parent: Parent window
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        messagebox.showwarning(title, message)
        root.destroy()
    else:
        messagebox.showwarning(title, message, parent=parent)

# 3. Error Message Box
def show_error(
    title: str = "Error",
    message: str = "An error occurred!",
    parent: Optional[tk.Tk] = None
) -> None:
    """
    Show an error message box

    Args:
        title: Dialog title
        message: Message text
        parent: Parent window
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        messagebox.showerror(title, message)
        root.destroy()
    else:
        messagebox.showerror(title, message, parent=parent)

# 4. Yes/No Question Box
def ask_yes_no(
    title: str = "Confirm",
    message: str = "Do you want to continue?",
    parent: Optional[tk.Tk] = None
) -> bool:
    """
    Show a yes/no question box

    Args:
        title: Dialog title
        message: Question text
        parent: Parent window

    Returns:
        True if Yes, False if No
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = messagebox.askyesno(title, message)
        root.destroy()
        return result
    else:
        return messagebox.askyesno(title, message, parent=parent)

# 5. OK/Cancel Question Box
def ask_ok_cancel(
    title: str = "Confirm",
    message: str = "Proceed with operation?",
    parent: Optional[tk.Tk] = None
) -> bool:
    """
    Show an OK/Cancel question box

    Args:
        title: Dialog title
        message: Question text
        parent: Parent window

    Returns:
        True if OK, False if Cancel
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = messagebox.askokcancel(title, message)
        root.destroy()
        return result
    else:
        return messagebox.askokcancel(title, message, parent=parent)

# 6. Yes/No/Cancel Question Box
def ask_yes_no_cancel(
    title: str = "Confirm",
    message: str = "Save changes before closing?",
    parent: Optional[tk.Tk] = None
) -> Optional[bool]:
    """
    Show a Yes/No/Cancel question box

    Args:
        title: Dialog title
        message: Question text
        parent: Parent window

    Returns:
        True if Yes, False if No, None if Cancel
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = messagebox.askyesnocancel(title, message)
        root.destroy()
        return result
    else:
        return messagebox.askyesnocancel(title, message, parent=parent)

# 7. Retry/Cancel Question Box
def ask_retry_cancel(
    title: str = "Retry",
    message: str = "Operation failed. Retry?",
    parent: Optional[tk.Tk] = None
) -> bool:
    """
    Show a Retry/Cancel question box

    Args:
        title: Dialog title
        message: Question text
        parent: Parent window

    Returns:
        True if Retry, False if Cancel
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = messagebox.askretrycancel(title, message)
        root.destroy()
        return result
    else:
        return messagebox.askretrycancel(title, message, parent=parent)

# 8. Simple String Input Dialog
def ask_string(
    title: str = "Input",
    prompt: str = "Enter value:",
    initialvalue: Optional[str] = None,
    parent: Optional[tk.Tk] = None
) -> Optional[str]:
    """
    Show a string input dialog

    Args:
        title: Dialog title
        prompt: Prompt text
        initialvalue: Initial value
        parent: Parent window

    Returns:
        Entered string or None if cancelled
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = simpledialog.askstring(title, prompt, initialvalue=initialvalue)
        root.destroy()
        return result
    else:
        return simpledialog.askstring(title, prompt, initialvalue=initialvalue, parent=parent)

# 9. Integer Input Dialog
def ask_integer(
    title: str = "Input",
    prompt: str = "Enter integer:",
    initialvalue: Optional[int] = None,
    minvalue: Optional[int] = None,
    maxvalue: Optional[int] = None,
    parent: Optional[tk.Tk] = None
) -> Optional[int]:
    """
    Show an integer input dialog

    Args:
        title: Dialog title
        prompt: Prompt text
        initialvalue: Initial value
        minvalue: Minimum value
        maxvalue: Maximum value
        parent: Parent window

    Returns:
        Entered integer or None if cancelled
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = simpledialog.askinteger(title, prompt, initialvalue=initialvalue, minvalue=minvalue, maxvalue=maxvalue)
        root.destroy()
        return result
    else:
        return simpledialog.askinteger(title, prompt, initialvalue=initialvalue, minvalue=minvalue, maxvalue=maxvalue, parent=parent)

# 10. Float Input Dialog
def ask_float(
    title: str = "Input",
    prompt: str = "Enter number:",
    initialvalue: Optional[float] = None,
    minvalue: Optional[float] = None,
    maxvalue: Optional[float] = None,
    parent: Optional[tk.Tk] = None
) -> Optional[float]:
    """
    Show a float input dialog

    Args:
        title: Dialog title
        prompt: Prompt text
        initialvalue: Initial value
        minvalue: Minimum value
        maxvalue: Maximum value
        parent: Parent window

    Returns:
        Entered float or None if cancelled
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()
        result = simpledialog.askfloat(title, prompt, initialvalue=initialvalue, minvalue=minvalue, maxvalue=maxvalue)
        root.destroy()
        return result
    else:
        return simpledialog.askfloat(title, prompt, initialvalue=initialvalue, minvalue=minvalue, maxvalue=maxvalue, parent=parent)

# 11. Custom Message Box with Icon
def show_custom_message(
    title: str,
    message: str,
    icon: str = "info",
    parent: Optional[tk.Tk] = None
) -> None:
    """
    Show a custom message box with specified icon

    Args:
        title: Dialog title
        message: Message text
        icon: Icon type ('info', 'warning', 'error')
        parent: Parent window
    """
    if parent is None:
        root = tk.Tk()
        root.withdraw()

        if icon == "info":
            messagebox.showinfo(title, message)
        elif icon == "warning":
            messagebox.showwarning(title, message)
        elif icon == "error":
            messagebox.showerror(title, message)
        else:
            messagebox.showinfo(title, message)

        root.destroy()
    else:
        if icon == "info":
            messagebox.showinfo(title, message, parent=parent)
        elif icon == "warning":
            messagebox.showwarning(title, message, parent=parent)
        elif icon == "error":
            messagebox.showerror(title, message, parent=parent)
        else:
            messagebox.showinfo(title, message, parent=parent)

# 12. Confirmation Dialog Chain
def confirm_action(
    steps: list,
    parent: Optional[tk.Tk] = None
) -> bool:
    """
    Show multiple confirmation dialogs in sequence

    Args:
        steps: List of (title, message) tuples
        parent: Parent window

    Returns:
        True if all confirmed, False otherwise
    """
    for title, message in steps:
        if not ask_yes_no(title, message, parent):
            return False
    return True

# 13. Progress Message Box
class ProgressMessageBox:
    """Message box with progress indication"""

    def __init__(self, title: str = "Progress", total: int = 100):
        """
        Initialize progress message box

        Args:
            title: Window title
            total: Total items to process
        """
        self.root = tk.Tk()
        self.root.title(title)
        self.total = total
        self.current = 0

        self.label = tk.Label(self.root, text="Processing...")
        self.label.pack(padx=20, pady=10)

        self.progress = tk.Label(self.root, text=f"0 / {total}")
        self.progress.pack(padx=20, pady=5)

    def update(self, increment: int = 1) -> None:
        """
        Update progress

        Args:
            increment: Amount to increment
        """
        self.current += increment
        self.progress.config(text=f"{self.current} / {self.total}")
        self.root.update()

    def close(self) -> None:
        """Close progress dialog"""
        self.root.destroy()

# 14. Notification Popup
def show_notification(
    title: str,
    message: str,
    duration: int = 3000
) -> None:
    """
    Show a temporary notification popup

    Args:
        title: Notification title
        message: Notification message
        duration: Display duration in milliseconds
    """
    root = tk.Tk()
    root.title(title)

    # Make window stay on top
    root.attributes('-topmost', True)

    # Remove window decorations
    root.overrideredirect(True)

    # Create message label
    label = tk.Label(
        root,
        text=message,
        bg='lightblue',
        fg='black',
        padx=20,
        pady=10,
        relief='raised',
        borderwidth=2
    )
    label.pack()

    # Center window
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    x = (root.winfo_screenwidth() // 2) - (width // 2)
    y = 50  # Near top of screen
    root.geometry(f'{width}x{height}+{x}+{y}')

    # Auto-close after duration
    root.after(duration, root.destroy)

    root.mainloop()

# 15. Choice Dialog
def ask_choice(
    title: str,
    message: str,
    choices: list,
    parent: Optional[tk.Tk] = None
) -> Optional[str]:
    """
    Show a choice selection dialog

    Args:
        title: Dialog title
        message: Prompt message
        choices: List of choices
        parent: Parent window

    Returns:
        Selected choice or None
    """
    root = tk.Tk() if parent is None else parent
    if parent is None:
        root.withdraw()

    # Create custom dialog
    dialog = tk.Toplevel(root)
    dialog.title(title)
    dialog.geometry("300x200")

    # Message
    label = tk.Label(dialog, text=message, wraplength=250)
    label.pack(pady=10)

    # Variable to store result
    result = [None]

    # Choice buttons
    for choice in choices:
        btn = tk.Button(
            dialog,
            text=choice,
            command=lambda c=choice: set_result(c)
        )
        btn.pack(pady=5, padx=20, fill='x')

    def set_result(value):
        result[0] = value
        dialog.destroy()

    dialog.wait_window()

    if parent is None:
        root.destroy()

    return result[0]

# Usage Examples
def demonstrate_message_boxes():
    """Demonstrate all message box examples"""
    print("=== Python Message Boxes Examples ===\n")

    # 1. Info box
    print("--- 1. Information Message Box ---")
    # show_info("Welcome", "This is an information message")

    # 2. Warning box
    print("\n--- 2. Warning Message Box ---")
    # show_warning("Warning", "This is a warning message")

    # 3. Error box
    print("\n--- 3. Error Message Box ---")
    # show_error("Error", "This is an error message")

    # 4. Yes/No
    print("\n--- 4. Yes/No Question ---")
    # answer = ask_yes_no("Confirm", "Do you want to proceed?")
    # print(f"User answered: {answer}")

    # 5. OK/Cancel
    print("\n--- 5. OK/Cancel Question ---")
    # answer = ask_ok_cancel("Confirm", "Continue operation?")
    # print(f"User answered: {answer}")

    # 6. Yes/No/Cancel
    print("\n--- 6. Yes/No/Cancel Question ---")
    # answer = ask_yes_no_cancel("Save", "Save changes?")
    # print(f"User answered: {answer}")

    # 7. Retry/Cancel
    print("\n--- 7. Retry/Cancel Question ---")
    # answer = ask_retry_cancel("Retry", "Try again?")
    # print(f"User answered: {answer}")

    # 8. String input
    print("\n--- 8. String Input Dialog ---")
    # name = ask_string("Input", "Enter your name:")
    # print(f"Name: {name}")

    # 9. Integer input
    print("\n--- 9. Integer Input Dialog ---")
    # age = ask_integer("Input", "Enter your age:", minvalue=0, maxvalue=120)
    # print(f"Age: {age}")

    # 10. Float input
    print("\n--- 10. Float Input Dialog ---")
    # price = ask_float("Input", "Enter price:", minvalue=0.0)
    # print(f"Price: {price}")

    # 11. Custom icon
    print("\n--- 11. Custom Icon Message ---")
    # show_custom_message("Custom", "Message with custom icon", icon="warning")

    # 12. Confirmation chain
    print("\n--- 12. Confirmation Chain ---")
    steps = [
        ("Step 1", "Confirm first step?"),
        ("Step 2", "Confirm second step?"),
        ("Step 3", "Confirm final step?")
    ]
    # result = confirm_action(steps)
    # print(f"All confirmed: {result}")

    # 13. Progress box
    print("\n--- 13. Progress Message Box ---")
    # progress = ProgressMessageBox("Processing", total=10)
    # for i in range(10):
    #     progress.update()
    #     time.sleep(0.5)
    # progress.close()

    # 14. Notification
    print("\n--- 14. Notification Popup ---")
    # show_notification("Notification", "Task completed!")

    # 15. Choice dialog
    print("\n--- 15. Choice Dialog ---")
    # choice = ask_choice("Select", "Choose an option:", ["Option A", "Option B", "Option C"])
    # print(f"Selected: {choice}")

    print("\n=== All Message Box Examples Completed ===")
    print("\nNOTE: Uncomment the dialog calls to see them in action")
    print("GUI dialogs require a desktop environment")

# Export functions
# export { show_info, show_warning, show_error }
# export { ask_yes_no, ask_ok_cancel, ask_yes_no_cancel, ask_retry_cancel }
# export { ask_string, ask_integer, ask_float }
# export { show_custom_message, confirm_action, ProgressMessageBox }
# export { show_notification, ask_choice }
# export { demonstrate_message_boxes }
CodepythonComplex

System Tray

Create system tray icons with menus, notifications, and window management

Difficulty

7/10

Estimated time

45 min

Tags

python, web, desktop, gui, system-tray

Prerequisites

Advanced Python, pystray, Pillow, Threading

python
# Web Python System Tray Examples
# System tray icon and menu functionality
#
# NOTE: These are desktop GUI features that require a desktop environment
# Install required packages:
#   pip install pystray Pillow
#
# For Linux: Additional requirements
#   - Ubuntu/Debian: sudo apt-get install python3-tk gir1.2-appindicator3-0.1
#   - Fedora: sudo dnf install python3-gobject python3-appindicator
#
# Run with: python system_tray_examples.py

import tkinter as tk
from threading import Thread
import time
from typing import Callable, Optional, List
from PIL import Image, ImageDraw
import sys

# Try to import pystray, provide fallback if not available
try:
    import pystray
    PYSTRAY_AVAILABLE = True
except ImportError:
    PYSTRAY_AVAILABLE = False
    print("Warning: pystray not available. Install with: pip install pystray Pillow")

# 1. Create Simple Tray Icon
def create_simple_icon(
    icon_name: str = "Simple App",
    menu_items: Optional[List[tuple]] = None,
    on_click: Optional[Callable] = None
) -> Optional['pystray.Icon']:
    """
    Create a simple system tray icon

    Args:
        icon_name: Name/tooltip for the icon
        menu_items: List of (label, callback) tuples
        on_click: Single click callback

    Returns:
        Icon object or None if pystray unavailable
    """
    if not PYSTRAY_AVAILABLE:
        print("pystray is required for system tray functionality")
        return None

    # Create a simple icon image
    image = create_icon_image((64, 64), color='blue')

    # Create menu
    if menu_items is None:
        menu_items = [
            ('Show', lambda: print("Show clicked")),
            ('Hide', lambda: print("Hide clicked")),
            ('Exit', lambda: exit_app())
        ]

    menu = pystray.Menu(
        *[pystray.MenuItem(label, callback) for label, callback in menu_items]
    )

    # Create icon
    icon = pystray.Icon(icon_name, image, menu=menu)

    # Set default click action
    if on_click:
        icon.on_click = on_click

    return icon

# 2. Create Icon Image
def create_icon_image(
    size: tuple = (64, 64),
    color: str = 'blue',
    text: Optional[str] = None
) -> 'Image.Image':
    """
    Create an icon image

    Args:
        size: Image size (width, height)
        color: Background color
        text: Optional text to draw on icon

    Returns:
        PIL Image object
    """
    width, height = size
    image = Image.new('RGB', size, color)
    draw = ImageDraw.Draw(image)

    if text:
        # Draw text centered
        from PIL import ImageFont
        try:
            font = ImageFont.truetype("arial.ttf", 20)
        except:
            font = ImageFont.load_default()

        # Get text bounding box
        bbox = draw.textbbox((0, 0), text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]

        # Calculate position
        x = (width - text_width) // 2
        y = (height - text_height) // 2

        draw.text((x, y), text, fill='white', font=font)
    else:
        # Draw a simple circle
        margin = 5
        draw.ellipse(
            [margin, margin, width - margin, height - margin],
            fill='white',
            outline=color
        )

    return image

# 3. Animated Tray Icon
class AnimatedTrayIcon:
    """System tray icon with animation"""

    def __init__(
        self,
        icon_name: str = "Animated Icon",
        colors: List[str] = None,
        interval: float = 0.5
    ):
        """
        Initialize animated tray icon

        Args:
            icon_name: Name for the icon
            colors: List of colors to cycle through
            interval: Animation interval in seconds
        """
        if not PYSTRAY_AVAILABLE:
            raise ImportError("pystray is required")

        self.icon_name = icon_name
        self.colors = colors or ['red', 'green', 'blue']
        self.interval = interval
        self.current_frame = 0
        self.running = False

        # Create initial icon
        self.image = create_icon_image(color=self.colors[0])
        self.icon = pystray.Icon(self.icon_name, self.image)

    def next_frame(self):
        """Advance to next animation frame"""
        self.current_frame = (self.current_frame + 1) % len(self.colors)
        self.icon.icon = create_icon_image(color=self.colors[self.current_frame])

    def run_animation(self):
        """Run animation loop"""
        self.running = True
        while self.running:
            self.next_frame()
            time.sleep(self.interval)

    def start(self):
        """Start the icon with animation"""
        # Start animation in separate thread
        animation_thread = Thread(target=self.run_animation, daemon=True)
        animation_thread.start()

        # Run icon
        self.icon.run()

    def stop(self):
        """Stop animation and icon"""
        self.running = False
        self.icon.stop()

# 4. Tray Icon with Window Management
class TrayApp:
    """Application with system tray integration"""

    def __init__(
        self,
        window_title: str = "Tray App",
        icon_name: str = "My App"
    ):
        """
        Initialize tray application

        Args:
            window_title: Main window title
            icon_name: Tray icon name
        """
        if not PYSTRAY_AVAILABLE:
            raise ImportError("pystray is required")

        self.window_title = window_title
        self.icon_name = icon_name
        self.window = None
        self.icon = None
        self.visible = True

    def create_window(self):
        """Create main application window"""
        self.window = tk.Tk()
        self.window.title(self.window_title)
        self.window.geometry("400x300")

        # Add content
        label = tk.Label(
            self.window,
            text=f"{self.window_title}\n\nMinimize me to tray!",
            font=('Arial', 14)
        )
        label.pack(expand=True)

        # Handle window close
        self.window.protocol("WM_DELETE_WINDOW", self.on_window_close)

    def on_window_close(self):
        """Handle window close - minimize to tray"""
        self.window.withdraw()
        self.visible = False

    def show_window(self):
        """Show and restore window"""
        if self.window is None:
            self.create_window()

        self.window.deiconify()
        self.window.lift()
        self.visible = True

    def hide_window(self):
        """Hide window"""
        if self.window:
            self.window.withdraw()
            self.visible = False

    def toggle_window(self):
        """Toggle window visibility"""
        if self.visible:
            self.hide_window()
        else:
            self.show_window()

    def exit_app(self):
        """Exit application"""
        if self.window:
            self.window.destroy()
        if self.icon:
            self.icon.stop()
        sys.exit(0)

    def run(self):
        """Run the application"""
        # Create window
        self.create_window()

        # Create tray icon
        image = create_icon_image(color='green')

        # Create menu
        menu = pystray.Menu(
            pystray.MenuItem('Show', self.show_window),
            pystray.MenuItem('Hide', self.hide_window),
            pystray.MenuItem('Exit', self.exit_app)
        )

        # Create icon
        self.icon = pystray.Icon(
            self.icon_name,
            image,
            menu=menu
        )

        # Set double-click to show window
        def on_double_click(icon, button, time):
            if button == pystray.MouseButton.LEFT:
                self.toggle_window()

        self.icon.on_double_click = on_double_click

        # Run icon in separate thread
        icon_thread = Thread(target=self.icon.run, daemon=True)
        icon_thread.start()

        # Run window main loop
        self.window.mainloop()

# 5. Tray Icon with Notifications
class NotificationTrayIcon:
    """System tray icon with notification support"""

    def __init__(
        self,
        icon_name: str = "Notifier",
        default_notification: str = "No new notifications"
    ):
        """
        Initialize notification tray icon

        Args:
            icon_name: Icon name
            default_notification: Default message
        """
        if not PYSTRAY_AVAILABLE:
            raise ImportError("pystray is required")

        self.icon_name = icon_name
        self.notifications = []
        self.default_notification = default_notification

        # Create icon
        image = create_icon_image(color='orange')
        self.icon = pystray.Icon(
            self.icon_name,
            image,
            title=self.default_notification
        )

        # Setup menu
        self.setup_menu()

    def setup_menu(self):
        """Setup tray menu"""
        menu = pystray.Menu(
            pystray.MenuItem('Show Notifications', self.show_notifications),
            pystray.MenuItem('Clear Notifications', self.clear_notifications),
            pystray.MenuItem('Exit', self.exit_app)
        )
        self.icon.menu = menu

    def add_notification(self, message: str):
        """
        Add a notification

        Args:
            message: Notification message
        """
        self.notifications.append({
            'message': message,
            'time': time.ctime()
        })

        # Update icon tooltip
        self.icon.title = f"{len(self.notifications)} new notifications"

        # Update icon to show notification state
        self.icon.icon = create_icon_image(color='red', text=str(len(self.notifications)))

    def show_notifications(self):
        """Show all notifications"""
        if not self.notifications:
            print("No notifications")
            return

        # Create popup window
        root = tk.Tk()
        root.title("Notifications")
        root.geometry("400x300")

        text = tk.Text(root, wrap='word')
        text.pack(expand=True, fill='both', padx=10, pady=10)

        for notif in self.notifications:
            text.insert('end', f"[{notif['time']}]\n{notif['message']}\n\n")

        text.config(state='disabled')

        # Close button
        btn = tk.Button(root, text="Close", command=root.destroy)
        btn.pack(pady=5)

        root.mainloop()

    def clear_notifications(self):
        """Clear all notifications"""
        self.notifications.clear()
        self.icon.title = self.default_notification
        self.icon.icon = create_icon_image(color='orange')

    def exit_app(self):
        """Exit application"""
        self.icon.stop()
        sys.exit(0)

    def run(self):
        """Run the icon"""
        self.icon.run()

# 6. Tray Icon with Status Indicator
class StatusTrayIcon:
    """System tray icon with status indicator"""

    STATUS_COLORS = {
        'online': 'green',
        'offline': 'gray',
        'busy': 'red',
        'away': 'yellow',
        'error': 'darkred'
    }

    def __init__(self, icon_name: str = "Status App"):
        """
        Initialize status tray icon

        Args:
            icon_name: Icon name
        """
        if not PYSTRAY_AVAILABLE:
            raise ImportError("pystray is required")

        self.icon_name = icon_name
        self.current_status = 'offline'

        # Create icon
        image = create_icon_image(color=self.STATUS_COLORS[self.current_status])
        self.icon = pystray.Icon(
            self.icon_name,
            image,
            title=f"Status: {self.current_status}"
        )

        # Setup menu with status options
        self.setup_menu()

    def setup_menu(self):
        """Setup menu with status options"""
        menu_items = []
        for status in self.STATUS_COLORS.keys():
            menu_items.append(
                pystray.MenuItem(
                    status.capitalize(),
                    lambda s=status: self.set_status(s)
                )
            )

        menu_items.append(pystray.MenuItem('Exit', self.exit_app))

        self.icon.menu = pystray.Menu(*menu_items)

    def set_status(self, status: str):
        """
        Set current status

        Args:
            status: Status to set
        """
        if status in self.STATUS_COLORS:
            self.current_status = status
            self.icon.icon = create_icon_image(
                color=self.STATUS_COLORS[status],
                text=status[0].upper()
            )
            self.icon.title = f"Status: {status}"
            print(f"Status changed to: {status}")

    def exit_app(self):
        """Exit application"""
        self.icon.stop()
        sys.exit(0)

    def run(self):
        """Run the icon"""
        self.icon.run()

# 7. Quick Actions Tray Icon
class QuickActionsTrayIcon:
    """System tray icon with quick actions"""

    def __init__(self, icon_name: str = "Quick Actions"):
        """
        Initialize quick actions tray icon

        Args:
            icon_name: Icon name
        """
        if not PYSTRAY_AVAILABLE:
            raise ImportError("pystray is required")

        self.icon_name = icon_name
        self.actions = {
            'Screenshot': self.take_screenshot,
            'Open Calculator': self.open_calculator,
            'Open Notepad': self.open_notepad,
            'Lock Screen': self.lock_screen
        }

        # Create icon
        image = create_icon_image(color='purple')
        self.icon = pystray.Icon(self.icon_name, image)

        # Setup menu with actions
        self.setup_menu()

    def setup_menu(self):
        """Setup menu with quick actions"""
        menu_items = [
            pystray.MenuItem(label, callback)
            for label, callback in self.actions.items()
        ]
        menu_items.append(pystray.MenuItem('Exit', self.exit_app))

        self.icon.menu = pystray.Menu(*menu_items)

    def take_screenshot(self):
        """Take a screenshot"""
        print("Screenshot action triggered")
        # Implementation would use PIL.ImageGrab or similar

    def open_calculator(self):
        """Open calculator"""
        import subprocess
        try:
            if sys.platform == 'win32':
                subprocess.Popen('calc.exe')
            elif sys.platform == 'darwin':
                subprocess.Popen(['open', '-a', 'Calculator'])
            else:
                subprocess.Popen('gnome-calculator')
        except Exception as e:
            print(f"Error opening calculator: {e}")

    def open_notepad(self):
        """Open notepad"""
        import subprocess
        try:
            if sys.platform == 'win32':
                subprocess.Popen('notepad.exe')
            elif sys.platform == 'darwin':
                subprocess.Popen(['open', '-a', 'TextEdit'])
            else:
                subprocess.Popen('gedit')
        except Exception as e:
            print(f"Error opening notepad: {e}")

    def lock_screen(self):
        """Lock screen"""
        import subprocess
        try:
            if sys.platform == 'win32':
                subprocess.Popen('rundll32.exe user32.dll,LockWorkStation')
            elif sys.platform == 'darwin':
                subprocess.Popen(['pmset', 'displaysleepnow'])
            else:
                subprocess.Popen(['gnome-screensaver-command', '-l'])
        except Exception as e:
            print(f"Error locking screen: {e}")

    def exit_app(self):
        """Exit application"""
        self.icon.stop()
        sys.exit(0)

    def run(self):
        """Run the icon"""
        self.icon.run()

# Usage Examples
def demonstrate_system_tray():
    """Demonstrate system tray functionality"""
    print("=== Python System Tray Examples ===\n")

    if not PYSTRAY_AVAILABLE:
        print("pystray is not installed. Install with:")
        print("  pip install pystray Pillow")
        print("\nSkipping system tray demonstrations.\n")
        return

    print("System tray functionality available!")
    print("\nChoose an example to run:")
    print("1. Simple Tray Icon")
    print("2. Animated Tray Icon")
    print("3. Tray App with Window Management")
    print("4. Notification Tray Icon")
    print("5. Status Indicator Tray Icon")
    print("6. Quick Actions Tray Icon")
    print("\nNOTE: Uncomment the example you want to run")

    # Example 1: Simple icon
    # icon = create_simple_icon("My App")
    # if icon:
    #     icon.run()

    # Example 2: Animated icon
    # animated = AnimatedTrayIcon("Animated", colors=['red', 'green', 'blue'])
    # animated.start()

    # Example 3: Window management
    # app = TrayApp("My Application", "MyApp")
    # app.run()

    # Example 4: Notifications
    # notifier = NotificationTrayIcon("Notifier")
    # notifier.add_notification("Welcome to the app!")
    # notifier.add_notification("New message received")
    # notifier.run()

    # Example 5: Status indicator
    # status = StatusTrayIcon("StatusApp")
    # status.run()

    # Example 6: Quick actions
    # actions = QuickActionsTrayIcon("QuickActions")
    # actions.run()

    print("\n=== System Tray Examples Completed ===")

# Export functions
# export { create_simple_icon, create_icon_image }
# export { AnimatedTrayIcon, TrayApp, NotificationTrayIcon }
# export { StatusTrayIcon, QuickActionsTrayIcon }
# export { demonstrate_system_tray }
# export { PYSTRAY_AVAILABLE }

Tools

Tools frequently paired with this sample

Related

Related sample collections

Tool usage guide

Sample-focused context for search and workflow understanding

Title

Web Python Desktop Features Samples

Description

Web Python desktop GUI examples including file dialogs, message boxes, and system tray functionality using tkinter

Overview

Web Python desktop GUI examples including file dialogs, message boxes, and system tray functionality using tkinter

When to use

  • Use this sample set when you want reference inputs for Web Python Desktop Features Samples.
  • Use it to preview output formats and compare related sample variants.

How it works

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

Use cases

  • File Dialogs
  • Message Boxes
  • System Tray

FAQ

What is included in Web Python Desktop Features Samples?

This page includes curated sample entries, related tools, and neighboring sample collections for Web Python Desktop Features Samples.

Home
Tools3197
Samples593
Visualizations461
Viewers103
Hubs229
Tags333
Images, Audio & Video655

Image, audio, and video processing, conversion, and optimization tools

Math, Date & Finance644

Calculators, numerics, date logic, statistics, and finance tools

Design & Color296

Color, layout, graphics, visual styling, and design helper tools

Text & Writing209

Writing, cleanup, formatting, extraction, and text analysis tools

Developer & Web193

Developer utilities, networking, web debugging, and automation helpers

Conversion & Encoding175

Format, file, archive, unit, and encoding conversion tools

UI Screenshot Structure Review and Development Handoff
Piano Sketch Creation, MIDI Review and Listening Demo Handoff
Retro Game Texture Review and Asset Handoff
Screenshot-Based Procedure Guide Review and Handoff
Responsive Page Change Review and Evidence Handoff

© 2026 Elysia Tools. All rights reserved.

DocsPricingAboutTerms of ServicePrivacy PolicyCookiesContact

Development

cURL to Python (requests) Converter

Convert a cURL command into a Python requests code snippet with headers, data, and method

Media

Chrome Web Store Screenshots Resized

Resize images to Chrome Web Store screenshot dimensions while preserving full content and aspect ratio for extension and app listings

Development

Python Regex Tester (re module)

Test Python re patterns online: (?P<name>…) named groups, (?P=name) backreferences, VERBOSE patterns, findall behavior, and \g<name> replace templates — plus ready-to-paste Python code.

Format Conversion

Web Push RFC 8030 Request + VAPID + RFC 8291 Payload Encryption Encoder

Encode a complete Web Push send: RFC 8291 aes128gcm payload encryption, RFC 8292 VAPID ES256 JWT, RFC 8030 headers, APNs/FCM cross-walk and decrypt round-trip verification.

Web & Internet

Web Search (SearXNG JSON)

Search the web through the s.stdlang.com SearXNG instance and return its JSON response for automation or downstream tools.

Design

Web Font Pairing Lab

Preview a heading + body Google Fonts pairing with weight and line-height controls, and copy a ready-to-paste CSS @import + variables snippet. Curated 22-face registry plus 7 proven pairing presets.

Swift

macOS Desktop Features Swift Samples

macOS Swift desktop-specific examples including file dialogs, message boxes, and system tray

Go

Web Desktop Features Go Samples

Web Go desktop-specific features examples including file dialogs, message boxes, and system tray

Rust

Web Desktop Features Rust Samples

Web Rust desktop-like features examples including file dialogs, message boxes, and system integration

TypeScript

Web Desktop Features TypeScript Samples

Web TypeScript desktop-specific features examples including file dialogs, message boxes, and system tray

C++

Windows Desktop Features C++ Samples

Windows C++ desktop-specific features including file dialogs, message boxes, and system tray

C#

Windows Desktop Features - C# Samples

Comprehensive C# desktop features examples for Windows platform including file dialogs, message boxes, and system tray integration