Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHESPTRUFRDEEN

Elysia Tools

导航

Python

Web Python 桌面功能示例

Web Python 桌面GUI示例,包括文件对话框、消息框和系统托盘功能

案例

这个案例集合中的条目

代码python中等

文件对话框

使用tkinter.filedialog打开和保存文件对话框、目录选择和文件信息

难度

5/10

预计时间

30 min

标签

python, web, desktop, gui, file-dialog

前置条件

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 }
代码python简单

消息框

使用tkinter.messagebox显示各种消息框,包括信息、警告、错误和问题对话框

难度

3/10

预计时间

20 min

标签

python, web, desktop, gui, message-box

前置条件

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 }
代码python复杂

系统托盘

创建带有菜单、通知和窗口管理的系统托盘图标

难度

7/10

预计时间

45 min

标签

python, web, desktop, gui, system-tray

前置条件

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 }

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

工具使用指南

帮助搜索与理解工作流的案例说明

标题

Web Python 桌面功能示例

描述

Web Python 桌面GUI示例,包括文件对话框、消息框和系统托盘功能

概览

Web Python 桌面GUI示例,包括文件对话框、消息框和系统托盘功能

适用场景

  • Use this sample set when you want reference inputs for Web Python 桌面功能示例.
  • Use it to preview output formats and compare related sample variants.

使用方式

  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.

常见用途

  • 文件对话框
  • 消息框
  • 系统托盘

常见问题

What is included in Web Python 桌面功能示例?

This page includes curated sample entries, related tools, and neighboring sample collections for Web Python 桌面功能示例.

首页
工具3197
案例593
可视化461
文件查看器103
专题229
标签333
图像、音频与视频655

图像、音频、视频处理、转换与优化工具

数学、日期与金融644

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色296

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

界面截图结构化、人工校对与开发交付
钢琴旋律草稿创作、MIDI 核验与试听样稿交付
复古游戏纹理制作、候选评审与素材交付
操作截图到可复核图文指南与培训交付
网页改版响应式视觉回归审核与证据交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Development

cURL 转 Python (requests)

将 cURL 命令转换为 Python requests 代码片段,包含请求头、数据和请求方法

Media

Chrome网上应用商店截图调整

将图片调整为Chrome网上应用商店截图尺寸,同时保留完整内容和原始宽高比例

Development

Python 正则测试器(re 模块)

在线测试 Python re 模块正则:(?P<name>…) 命名组、(?P=name) 反向引用、VERBOSE 模式、findall 行为与 \g<name> 替换模板——附可直接粘贴的 Python 代码。

Format Conversion

Web Push RFC 8030 请求 + VAPID + RFC 8291 负载加密编码器

编码完整的 Web Push 发送流程:RFC 8291 aes128gcm 负载加密、RFC 8292 VAPID ES256 JWT、RFC 8030 头部、APNs/FCM 头部对照与解密往返验证。

Web & Internet

Web 搜索(SearXNG JSON)

通过 s.stdlang.com 的 SearXNG 实例搜索网页,返回 JSON 结果供自动化或后续工具使用。

Design

网页字体配对实验室

并排预览 标题 + 正文 的 Google 字体配对,调节字重与行高,复制即可粘贴的 CSS @import + 变量代码。精选 22 款字体及 7 组经典搭配预设。

Swift

macOS Swift 桌面端功能示例

macOS Swift 桌面端专用功能示例,包括文件对话框、消息框和系统托盘

Go

Web Go 桌面端功能示例

Web Go 桌面端特定功能示例,包括文件对话框、消息框和系统托盘

Rust

Web Rust 桌面端功能示例

Web Rust 桌面端功能示例,包括文件对话框、消息框和系统集成

TypeScript

Web TypeScript 桌面端功能示例

Web TypeScript 桌面端功能示例,包括文件对话框、消息框和系统托盘

C++

Windows C++ 桌面功能示例

Windows C++ 桌面专用功能示例,包括文件对话框、消息框和系统托盘

C#

Windows 桌面端功能 - C# 示例

Windows平台C#桌面端功能示例,包括文件对话框、消息框和系统托盘集成