Exemples de Fonctionnalités de Bureau Web Python

Exemples GUI de bureau Web Python incluant les boîtes de dialogue de fichiers, les boîtes de messages et les fonctionnalités de la barre d'état du système

💻 Boîtes de Messages python

🟢 simple ⭐⭐

Afficher diverses boîtes de messages y compris info, avertissement, erreur et boîtes de dialogue de questions en utilisant tkinter.messagebox

⏱️ 20 min 🏷️ python, web, desktop, gui, message-box
Prerequisites: Basic Python, tkinter module
# 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 }

💻 Boîtes de Dialogue Fichiers python

🟡 intermediate ⭐⭐⭐

Ouvrir et enregistrer les boîtes de dialogue de fichiers, la sélection de répertoire et les informations de fichiers en utilisant tkinter.filedialog

⏱️ 30 min 🏷️ python, web, desktop, gui, file-dialog
Prerequisites: Intermediate Python, tkinter module
# 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 }

💻 Barre d'État du Système python

🔴 complex ⭐⭐⭐⭐

Créer des icônes de la barre d'état du système avec des menus, des notifications et la gestion des fenêtres

⏱️ 45 min 🏷️ python, web, desktop, gui, system-tray
Prerequisites: Advanced Python, pystray, Pillow, Threading
# 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 }