Skip to main content

py-gui

Build and review cross-platform Python desktop applications with tkinter, ttk, CustomTkinter, PySide6, or PyQt6. Use for windows, widgets, layouts, dialogs, system tray, background jobs, event loops, model-view separation, accessibility, high-DPI behavior, settings, packaging with PyInstaller or Nuitka, and fixing unsafe worker-thread UI updates.

معلومات المصدر

المستودع
stevenke1981/python_skills
آخر نشاط في المصدر
٣٠ يوليو ٢٠٢٦ في ١٤:٠٥
لغة SKILL.md المكتشفة
الصينية
النجوم
١
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
py-gui
description
Build and review cross-platform Python desktop applications with tkinter, ttk, CustomTkinter, PySide6, or PyQt6. Use for windows, widgets, layouts, dialogs, system tray, background jobs, event loops, model-view separation, accessibility, high-DPI behavior, settings, packaging with PyInstaller or Nuitka, and fixing unsafe worker-thread UI updates.
compatibility
Agent Skills-compatible. GUI, native packaging, and platform integration require testing on each target operating system.
metadata
{"author":"stevenke1981","version":"2.0.0","last-reviewed":"2026-07-30"}
# Python GUI 桌面應用 ## 目標與邊界 用此 skill 建立可維護、不中斷 UI event loop、能正確取消背景工作的桌面應用。先選擇符合授權、平台與功能需求的框架,再設計狀態、執行緒與打包流程。 若只是終端機互動,使用 `py-cli`;若 UI 只是 Web 前端,使用對應 Web 技術,不要為了桌面外殼強行使用 Python GUI。 ## 執行流程 1. **定義平台與交付方式**:Windows、macOS、Linux、安裝程式、portable、簽章與自動更新。 2. **選擇框架**:依 widget 複雜度、授權、原生整合、團隊經驗與打包成本決定。 3. **分離狀態與視圖**:domain/model 不 import GUI framework;view 不直接承擔資料存取與長任務。 4. **設計 event loop 邊界**:所有 UI 讀寫在主執行緒;背景工作只透過 queue、signal 或 message 回傳。 5. **加入取消與錯誤回報**:長工作可取消、可逾時,錯誤轉成使用者可理解訊息。 6. **驗證可用性**:鍵盤操作、focus、縮放、字型、深淺色、螢幕閱讀器與多螢幕。 7. **打包與原生測試**:在每個目標 OS 測試啟動、資源、權限、檔案關聯、更新與移除。 ## 框架選擇 | 需求 | 優先考慮 | 注意事項 | |---|---|---| | 小型內部工具、零額外 GUI 依賴 | tkinter / ttk | 外觀與高階 widget 較有限 | | 快速做現代化 tkinter UI | CustomTkinter | 仍遵守 Tk 主執行緒規則 | | 大型桌面產品、model/view、WebEngine、多媒體 | PySide6 | Qt 官方 Python binding;確認 LGPL 義務 | | 既有 PyQt 團隊或商業授權 | PyQt6 | 確認 GPL/商業授權條件 | | 終端機全螢幕介面 | Textual | 改讀 `py-cli` 為主 | 不要只根據外觀選框架。原生能力、可測試性、授權與安裝包大小通常更重要。 ## 主執行緒規則 - Tk、Qt 與大多數 GUI toolkit 都要求 UI 操作留在主執行緒。 - worker 不直接呼叫 widget method,也不要假設從 worker 呼叫 `after()` 永遠安全。 - worker 只處理計算或 I/O,透過 thread-safe queue 或 Qt signal 回傳事件。 - 關閉視窗時先發出取消,再等待資源安全釋放。 - 不在 click handler 中執行模型下載、網路請求、資料庫 migration 或大型檔案解析。 ### tkinter/CustomTkinter queue 模式 ```python from __future__ import annotations import time from dataclasses import dataclass from queue import Empty, Queue from threading import Event, Thread import customtkinter as ctk @dataclass(frozen=True, slots=True) class ProgressEvent: percent: int message: str def run_job(events: Queue[ProgressEvent], cancelled: Event) -> None: for percent in range(101): if cancelled.is_set(): events.put(ProgressEvent(percent, "已取消")) return time.sleep(0.03) events.put(ProgressEvent(percent, "處理中")) class App(ctk.CTk): def __init__(self) -> None: super().__init__() self.title("Background Job") self.events: Queue[ProgressEvent] = Queue() self.cancelled = Event() self.worker: Thread | None = None self.progress = ctk.CTkProgressBar(self) self.progress.pack(padx=20, pady=12) self.status = ctk.CTkLabel(self, text="等待中") self.status.pack(padx=20, pady=12) ctk.CTkButton(self, text="開始", command=self.start_job).pack() ctk.CTkButton(self, text="取消", command=self.cancelled.set).pack() def start_job(self) -> None: if self.worker is not None and self.worker.is_alive(): return self.cancelled.clear() self.worker = Thread( target=run_job, args=(self.events, self.cancelled), daemon=True, ) self.worker.start() self.after(50, self.poll_events) def poll_events(self) -> None: try: while True: event = self.events.get_nowait() self.progress.set(event.percent / 100) self.status.configure(text=event.message) except Empty: pass if self.worker is not None and self.worker.is_alive(): self.after(50, self.poll_events) if __name__ == "__main__": App().mainloop() ``` 正式應用需再處理視窗關閉時的取消、worker join、例外事件與重複啟動。 ## Qt Signal/Slot 規則 - 長工作使用 `QThread`, `QThreadPool`/`QRunnable` 或 async integration,不把工作塞進主 event loop。 - worker 透過 typed signal 傳送不可變資料。 - QObject 的 thread affinity 必須清楚;不要任意在執行後移動有 parent 的物件。 - view model 保留可測試狀態;signal handler 只做短操作。 - 大量更新要節流或批次,避免每筆資料都 repaint。 ## 佈局與狀態 ### tkinter - `pack`、`grid` 可在不同 parent 使用,但不要在同一 parent 混用。 - 混用通常造成 geometry manager 錯誤,而不是所謂「無限迴圈」。 - 表單優先 `grid`,簡單線性區塊可用 `pack`。 - 不以 `place` 固定所有像素;需考慮 DPI、字型與翻譯後長度。 ### 狀態管理 - domain model 不依賴 GUI import。 - 設定與 session state 使用 dataclass/Pydantic 等明確結構。 - view 只保存呈現需要的狀態。 - 儲存前驗證,使用 atomic write,避免程式中斷造成設定檔損壞。 - 不在 UI state 內保存裸 API key;使用 OS credential store 或安全 secret 來源。 ## 錯誤與使用者體驗 - 技術例外寫入 log,對使用者顯示可行動訊息。 - 非致命錯誤不要讓主 event loop 崩潰。 - 需要時間的操作顯示 progress、可取消與明確完成狀態。 - 防止 double-click 重複提交;disable/enable 按鈕與 operation state 一致。 - 對破壞性操作提供確認與可回復機制。 - 所有主要操作可使用鍵盤,focus order 合理。 ## 打包與發布 1. 先用一般 venv 執行完整 smoke test。 2. 明確列出動態 import、Qt plugin、圖示、翻譯與資料檔。 3. 先測 one-folder,再決定是否 one-file;one-file 常有較慢啟動與防毒誤判成本。 4. 在乾淨 VM 或實體機測試,不只在開發機。 5. 分別驗證 Windows code signing、macOS signing/notarization 與 Linux desktop integration。 6. 記錄 log/cache/config 位置與升級遷移策略。 7. 若有自動更新,更新包必須簽章並可回復。 ## 測試策略 - domain/model 使用一般單元測試。 - controller/view model 使用 fake view 或 signal spy。 - 對 thread/queue 測試完成、取消、例外與 shutdown。 - UI smoke test 覆蓋啟動、主要流程與視窗關閉。 - 在 CI 或 release pipeline 執行每個 OS 的打包與啟動測試。 - screenshot test 只作輔助;不要以像素完全相同取代可用性測試。 ## 交付標準 - UI 操作只在主執行緒,worker 透過 queue/signal 回傳。 - 長工作可取消,關閉時不留下 thread、process、socket 或暫存檔。 - domain/model 不依賴 GUI framework,可獨立測試。 - 佈局支援 DPI、字型與文字長度變化。 - 錯誤、進度、重複操作與破壞性動作有清楚 UX。 - 每個目標 OS 都有打包與乾淨環境 smoke test。 - 授權、簽章、更新與設定儲存策略已記錄。 ## 延伸閱讀 - [完整範例](references/examples.md) - [速查表](references/cheatsheet.md) - [常見陷阱](references/pitfalls.md) ## 版本相容性 | 環境 | 建議 | |---|---| | Python 3.14 | 穩定維護基準;確認 GUI framework 與 bundler wheel | | Python 3.10–3.13 | 支援;依目標框架的官方支援矩陣 | | Windows/macOS/Linux | 必須分別打包與 smoke test | | PySide6/PyQt6 | Qt plugin、授權與部署規則需依實際版本確認 | | Preview Python | 不作發行預設,除非 bundler 與 native wheels 已驗證 |
عرض على GitHub