为什么选择原生桌面框架

过去两年里,我反复被问到一个问题:既然 Web 技术这么方便,为什么还要用 PyQt 写桌面应用?

答案通常只有一个:离线优先。当用户没有网络、或者不愿意把数据交给第三方服务器时,一个能直接读写本地文件、启动即用的原生程序,体验是网页无法替代的。

三个关键约束

  1. 程序必须完全独立运行,不能依赖浏览器或外部运行时;
  2. 所有数据落在本地,允许用户自行备份;
  3. 界面必须是中文,且在高分屏下保持锐利。

窗口结构怎么设计

我习惯把主窗口拆成三块:左侧导航、顶部工具条、右侧内容区。用一个 QStackedWidget 承载页面,切换时只更新标题与操作按钮,避免窗口重建带来的闪烁。

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.stack = QStackedWidget()
        self.setCentralWidget(self.stack)
        for page in (DashboardPage(), ProjectPage(), SettingsPage()):
            self.stack.addWidget(page)

主题系统

不要在业务代码里硬编码颜色。定义一个 Theme 单例,集中维护背景、正文、强调色与分割线,切换深色模式时只需要替换一份色板,并调用一次 repaint()。

经验:颜色越少,界面越稳。一个主色加两级灰阶,足够覆盖 90% 的场景。

打包发布

用 PyInstaller 生成单文件版本最省事,但启动会慢 1-2 秒;如果对启动速度敏感,可以改成目录模式,再配合安装包脚本。无论哪种方式,记得把 Qt 插件目录 一起带上,否则到用户机器上会报平台插件缺失。

小结

原生桌面不是「复古」,而是把复杂度留在本地、把确定性交给用户。下一篇文章我会讲讲如何用 Cython 把核心模块编译成 .pyd,在不影响开发体验的前提下保护源码。