尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于PyQt6的本地快捷启动器:统一管理软件、文档、文件夹与网址

基于PyQt6的本地快捷启动器:统一管理软件、文档、文件夹与网址 你有没有这种感觉浏览器书签栏攒了几百个链接桌面上铺满快捷方式硬盘里的文档散落在七八个文件夹每次开工前光找入口就要花掉五分钟。我就是被这种“找东西”的体验折磨到忍无可忍才动手做了这个编号 806 的小项目——一个列表版快捷管理工具专门把软件、文档、文件夹、网址四类高频入口收进同一个窗口双击就能跳转搜索就能过滤。它解决的核心问题就一句话让电脑上所有常用的东西都能在一个地方被秒速找到、一键打开。我这个工具没有做什么花哨的界面也没有云端账号体系就是一个本地窗口左边是分类右边是列表顶部一个搜索框。它不像浏览器书签那样只能在网页里跳也不像桌面快捷方式那样铺得满屏都是而是把所有我能用到的入口——不管是某个软件的 exe、某个项目的文件夹、某篇常看的 PDF还是某个内部系统的后台地址——全部结构化地放在一个 JSON 配置里程序启动时一次性加载出来。今天这篇就把我从选题到实现的完整过程包括踩过的坑和排查经验一并分享出来。1. 项目起点被几百个“入口”淹没之后1.1 这个“列表版”工具到底解决了什么问题先说痛点。我做内容整理和工具评测相关工作日常工作流里至少涉及四类高频入口软件剪辑工具、截图工具、压缩软件、数据库客户端、文档合同 PDF、操作手册、表格模板、文件夹素材库、输出目录、备份盘、网址各类后台、文档站点、图库、搜索引擎。以前这些东西分布在哪呢软件在开始菜单和桌面文档在微信文件传输助手和下载目录里乱躺文件夹要一层层点进资源管理器网址则散落在浏览器书签的十几个子文件夹里。每天开工的第一件事就是把这些入口一个个找齐。更麻烦的是有些工具一个月才用一次名字记不清图标认不出等要用的时候翻半天才能找到。我算了一笔账平均每次找入口花 2 分钟一天找十次就是 20 分钟一周就是两个小时。这个成本绝对值得用一个工具来解决。所以这个项目的第一条需求非常明确要有一个统一的入口清单把软件、文档、文件夹、网址全部收纳进去并且以文本列表的形式展示而不是图标墙。文本列表的好处是信息密度高扫一眼就知道这是什么而图标墙在条目多的时基本只能靠猜。1.2 适合谁用不适合谁用用这个工具最舒服的人群我认为有三类。第一类是像我做评测、做内容的人手头有大量的素材目录和工具软件第二类是办公族每天要开固定的一套软件、固定的一批网页后台还要频繁访问公司共享盘里的几个文件夹第三类是轻度软件收藏癖见到好用的工具就想留下来装完又老忘记放哪里。不适合的情况也有。如果你电脑上常用的软件就五六个网址也就常看三四个那用系统自带的任务栏固定和浏览器书签就够了没必要再套一层工具。还有就是特别在意界面颜值的人我这个工具偏向实用不会做成那种毛玻璃加动画的酷炫启动器。它更像是给“数字杂物太多的人”准备的整理箱。另外提示一点这类工具本质上是一个“入口聚合层”它不会接管你文件的真实路径也不会把你收藏的网址同步到云端所以就算工具本身出问题也不会影响原来的文件和网站。2. 设计思路为什么是列表版而不是花哨的网格2.1 列表版在信息密度和维护性上的优势我在动手之前其实先考虑了两种主流展示形态网格卡片版与列表版。网格卡片就是类似手机桌面那种每个入口一个方格子带图标带标题视觉冲击力强列表版则是像 Excel 表或资源管理器“详细信息”视图那样一行一条记录字段对齐排开。最终选列表版有三个决定性原因。第一是信息密度在同样的 1080p 屏幕高度内网格卡片大概只能展示 12 到 16 个条目而列表可以轻松展示 20 到 30 条一屏能看到的内容量翻倍。第二是扫读效率人眼对逐行对齐的文字的扫描速度远快于在二维网格中定位图标列表里“类型、名称、路径”三列对齐扫过去就能直接锁定目标。第三是维护体验列表的行高统一分类、改名、调整排序都在纯文本层面完成不需要设计图标、处理卡片间距之类的视觉细节。当然列表版也有它的短板比如缺少图标会导致辨识度打折。我的补偿方案是在类型列上加一个简短的标签文案比如“软件”“文档”“文件夹”“网址”同时在名称列用颜色区分类型这样既保留了列表的密度也不至于一眼看过去全是白底黑字。2.2 数据结构先行用 JSON 把一切“入口”统一成一条记录这个工具最核心的设计决策就是“一切皆记录”。不管是软件、文档、文件夹还是网址都抽象成同一条数据结构只是类型字段不同。我用的配置文件是 JSON 格式结构如下{ version: 1, categories: [工作, 学习, 工具, 素材], items: [ { id: a001, name: 项目素材总目录, type: folder, target: D:\\work\\assets, category: 素材, remark: 所有剪辑素材和源文件 }, { id: a002, name: 系统后台, type: url, target: https://admin.example.com, category: 工作, remark: 内容发布后台 }, { id: a003, name: 产品手册, type: doc, target: D:\\docs\\product-manual.pdf, category: 学习, remark: 最新版操作手册 } ] }每条记录的核心字段就四个name 是给人看的名称type 决定启动方式target 是真实路径或网址category 用于分组。id 字段主要是为了后续做拖拽排序和同步留的锚点如果没有这个需求可以省略。remark 是备注字段我习惯把一些容易忘记的账号信息、使用注意事项塞进去鼠标悬停就能看到。这个结构化设计的好处非常明显程序读配置只需要做一次 JSON 解析后续不管是搜索、分类过滤还是双击启动都只跟这一份数据打交道。数据与逻辑完全分离就算以后我想换界面把列表改成树形或卡片配置文件一行都不用动。2.3 分类与使用场景单级分类真的够用吗很多同类工具喜欢做多级嵌套分类比如“工作—项目A—文档”。我一开始也想过加二级分类但后来实际梳理自己的需求发现单级分类完全够用。原因很简单这个工具是“启动器”不是“文件管理器”它的目的是快速跳转不是整理归档。如果分类嵌套层级太多点击次数增加反而违背了“一键到达”的初衷。我最终的分类逻辑是按“使用场景”分而不是按“资源类型”分。因为“类型”已经在 type 字段里体现了而“场景”更能决定你什么时候会想起来用某个入口。比如我分了“工作”“学习”“工具”“素材”四个大类“工作”里既有网址也有文件夹还有软件这是因为我在工作日打开它们时是一个连续的场景。在实际使用中我也建议你按自己的习惯重新定义这些分类分类数量尽量控制在 5 到 8 个太多了列表侧边栏本身就成了一种负担。如果某天发现一个类目下超过 40 条记录就该考虑把里面的条目再拆分或者按名称频率调整排序而不是盲目增加层级。3. 技术选型与关键实现PyQt6 方案怎么落地3.1 桌面方案对比PyQt6、Electron 与 C# WPF确定了数据模型之后就要选实现载体。我认真对比了三个主流方案Python 加 PyQt6、Electron 加 Vue、C# 加 WPF。它们各自的优缺点很明显。Electron 的优势是界面表现力极强生态里像拖拽排序有 vuedraggable 这样的成熟组件开发效率很高但劣势是打包体积基本在 100MB 以上内存占用轻松突破 300MB对一个只有几百条记录的启动器来说实在有点杀鸡用牛刀。C# WPF 在 Windows 上表现很好系统集成度高但跨平台基本不想我平时要在 Windows 和 macOS 之间切换所以直接放弃。PyQt6 是我最终的选择。它的打包体积可以控制在 50MB 左右运行内存占用在 80MB 上下跨平台支持好而且我对 Python 更熟。虽然它的界面定制自由度不如前端方案但对列表型工具来说完全够用。QTreeWidget、QListWidget、QLineEdit 这些标准组件组合一下就能实现九成需要的交互。3.2 主界面布局搜索框加分类栏加列表区三板斧界面布局我做得非常朴素就三个区域。顶部是一个搜索框占一整行左侧是分类列表宽 140 像素左右右侧是条目列表用表格形式展示分成“名称”“类型”“备注”三列。整个窗口默认大小是 960 乘 640可以自由拉伸拉伸时右侧列表跟随扩展。搜索框这个组件是整个工具的灵魂所在它的过滤逻辑是输入关键词后先在当前分类内过滤匹配范围为“名称 备注 目标路径”三字段的模糊匹配如果当前分类过滤结果为空就自动扩展到全部分类。这样设计是为了避免用户在某个分类下搜索时明明全局有结果却因为分类限制而找不到造成“明明有这个入口却搜不出来”的挫败感。右侧列表我选用了 QTableWidget 而不是 QListWidget原因是我需要同时展示“名称”和“备注”两个字段列表模式用 QListWidget 只能显示一行文本信息不够如果不想用表格也可以用 QListView 配合自定义数据模型但开发量会大不少。实际使用下来QTableWidget 加三列配置已经能满足需求性能也很好。3.3 启动器核心逻辑文件、文件夹、网址、文档四种类型怎么处理列表界面只是皮真正的核心是双击条目之后的“根据类型做出正确动作”。这部分逻辑写在 doubleClicked 信号的处理函数里我把它称为 dispatch 函数。核心代码思路大致是这样from PyQt6.QtWidgets import QTableWidget, QTableWidgetItem, QApplication from PyQt6.QtCore import pyqtSlot import os, subprocess, webbrowser from PyQt6.QtGui import QDesktopServices from PyQt6.QtCore import QUrl def launch_item(self, item: dict): itype item[type] target item[target] if itype folder: # Windows 直接打开资源管理器macOS 用 openLinux 用 xdg-open if os.name nt: os.startfile(target) # noqa elif sys.platform darwin: subprocess.Popen([open, target]) else: subprocess.Popen([xdg-open, target]) elif itype url: webbrowser.open(target) elif itype doc: # 文档用系统默认程序打开效果等同于双击该文件 if os.name nt: os.startfile(target) elif sys.platform darwin: subprocess.Popen([open, target]) else: subprocess.Popen([xdg-open, target]) elif itype app: subprocess.Popen([target]) else: QDesktopServices.openUrl(QUrl.fromLocalFile(target))这里最容易被忽略的细节是“文档”和“程序”的处理差异。文档我希望调用系统默认打开方式比如 PDF 用浏览器、Word 用 Office而程序我要直接启动 exe 或命令行入口所以用 subprocess.Popen 让它后台剥离。文件夹则不能直接用 QDesktopServices.openUrl因为系统可能弹出“文件资源管理器”而不是直接打开指定目录。真正实现时还要考虑 target 可能带参数比如某个软件需要带启动参数那 target 就不仅是路径而是一个完整命令行字符串。我的方案是 app 类型单独加了一个可选字段 args用 shlex.split 拆分后传给 subprocess。3.4 配置文件读写与全局热键配置文件的路径我放在用户数据目录下Windows 上就是C:\Users\你的用户名\AppData\Roaming\QuickLauncher\config.jsonmacOS 和 Linux 则放在~/.config/quicklauncher/。这样做的好处是重装系统或迁移用户时配置文件能随系统用户目录一起走不会因为装在软件安装目录导致权限问题。读写代码没有太多玄机就是标准的 json.load 和 json.dump。但有两个细节必须注意第一是必须加encodingutf-8否则 Windows 下中文会乱码第二是写回时要先写临时文件再替换避免程序崩溃导致配置文件损坏。我之前图省事直接覆盖写结果有一次断电把配置写坏了几百条记录差点归零从那以后就老实改成“写临时文件 os.replace”方案了。全局热键是“快捷管理工具”体验重要的一环。我用的是 keyboard 库注册一个CtrlAltL组合键按下后把主窗口从隐藏状态唤醒到最前台。在 PyQt 环境里调用线程需要注意keyboard 的回调是在独立线程跑的不能直接操作 Qt 界面需要用信号槽机制把“显示窗口”这个动作发给主线程执行。没有做这一步的话程序大概率会闪退或卡死。4. 实操过程从零搭建这个工具的完整步骤4.1 搭骨架窗口、列表、数据加载我习惯先做一个能跑的骨架再往里填功能。第一步就是创建主窗口类在__init__里初始化三个区域然后调用load_config()读取 JSON 文件。核心骨架代码大致如下import sys, json, os from PyQt6.QtWidgets import ( QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QLineEdit, QListWidget, QTableWidget, QAbstractItemView, QTableWidgetItem, QHeaderView, QApplication ) class QuickLauncher(QMainWindow): def __init__(self): super().__init__() self.config_path self._get_config_path() self.config self.load_config() self.categories self.config.get(categories, []) self.items self.config.get(items, []) self.setWindowTitle(Quick Launcher - 806) self.resize(960, 640) self._build_ui() self.load_category_list() def _build_ui(self): central QWidget() self.setCentralWidget(central) root_layout QVBoxLayout(central) self.search_box QLineEdit() self.search_box.setPlaceholderText(输入关键词搜索软件 / 文档 / 文件夹 / 网址...) root_layout.addWidget(self.search_box) middle_layout QHBoxLayout() self.category_list QListWidget() self.category_list.setMaximumWidth(160) middle_layout.addWidget(self.category_list) self.table QTableWidget(0, 3) self.table.setHorizontalHeaderLabels([名称, 类型, 备注]) self.table.verticalHeader().setVisible(False) self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch) middle_layout.addWidget(self.table) root_layout.addLayout(middle_layout)这段代码建立了整个应用的视觉框架。QTableWidget 设置成“行选择 不可编辑”非常关键否则用户点一下就会进入编辑状态体验很差。表头列宽让第一列自适应拉伸备注列则采用默认宽度这样条目多的时候名称列能撑开不会出现长路径把布局挤爆的问题。4.2 写配置JSON 文件字段设计的几个建议配置文件的字段设计我在前文已经给了示例这里再补充几个经验。第一条建议是 id 字段最好用随机短码而不是自增序号比如a001、a002这种好处是未来做同步合并时不会因为两个设备都插入了相同序号而冲突如果你的配置只在一台机器上用自增序号也可以。第二条建议是 target 字段统一使用绝对路径。我知道很多教程会教用相对路径但快捷管理工具的使用场景决定了它不应该依赖“当前工作目录”因为双击启动时工作目录不一定是你写配置时的目录。绝对路径虽然不便于移植但可以配合“配置目录下放一个 paths.json 做路径映射”来解决比如把所有D:\work统一定义成%WORK%载入时再替换这样兼顾了可移植性和稳定性。第三条建议是给每条记录增加一个count字段专门记录这个入口被打开的累计次数。这个字段初期看起来没用但用一段时间后完全可以通过它自动把高频入口排到列表前面。我在骨架版本里就预留了这字段后续的“智能排序”功能就是基于它的。4.3 实现双击启动与新增条目双击启动的代码我已经在前面展示过但还有两个小细节要单独说。第一双击事件获取到的行号要反查回真实的记录条目而不是直接用行号索引数组。因为一旦启用了搜索过滤界面上的行号跟数据列表的索引不是一一对应的。解决办法是在填充表格时把每条记录的数据对象用setData(Qt.ItemDataRole.UserRole, item)存到条目里双击时取出来用。第二新增条目的交互。我做了两种方式一个是在界面上通过按钮弹窗录入另一个是直接编辑 JSON 文件后按 F5 刷新。实际使用中我发现弹窗录入更常用所以我做了个简化版的新增对话框字段就四个名称、类型、目标、备注类型用下拉框选择。录入完之后校验一下 target 是否为空如果类型是文件或文件夹还可以调用os.path.exists检查路径是否存在不存在时弹个警告防止眼滑填错。def add_item_from_dialog(self): # 伪代码只展示校验逻辑 name dialog.name_edit.text().strip() itype dialog.type_combo.currentText() target dialog.target_edit.text().strip() if not name or not target: QMessageBox.warning(self, 提示, 名称和目标不能为空) return if itype in (app, doc, folder) and not os.path.exists(target): ret QMessageBox.question( self, 路径检查, 目标路径不存在仍要添加吗 ) if ret QMessageBox.StandardButton.No: return new_item { id: fa{int(time.time())}, name: name, type: itype, target: target, category: current_category, remark: remark, } self.items.append(new_item) self.save_config() self.refresh_table()那个“路径不存在时二次确认”的校验是我在实际使用中加上的。没有它之前我经常把D:\work\素材打成D:\work\素才直到双击没反应才发现回头查配置又费了半天。现在填错的概率大大降低了。4.4 加入搜索与热键日常使用才算真的顺手骨架能跑、能增删之后接下来就是我体验差异最大的两件事搜索过滤与全局热键。搜索过滤我用的是 QTableWidget 的setRowHidden方式实现。思路很简单每次过滤条件变化时遍历表格所有行判断当前行的关键词是否匹配匹配就setRowHidden(False)显示不匹配就隐藏。这个方法在几百行记录下性能毫无压力代码也好写比重建模型要直观得多。def filter_table(self, keyword: str): keyword keyword.lower().strip() for row in range(self.table.rowCount()): item self.table.item(row, 0) remark_item self.table.item(row, 2) text (item.text() remark_item.text()).lower() match keyword in text self.table.setRowHidden(row, not match)这里有一个细节如果用户点击了左侧某个分类搜索就只在该分类内那些未隐藏的行里做过滤如果没有选分类就全表搜。我实现时用一个current_category变量记录分类状态过滤函数会根据它决定用哪一行集合。全局热键我之前提到用 keyboard 库这里补充一下注册回调的代码模式import keyboard def register_global_hotkey(self): keyboard.add_hotkey(ctrlaltl, self._show_from_hotkey) def _show_from_hotkey(self): self.showNormal() self.activateWindow() self.raise_() self.search_box.setFocus()但直接这么写会有线程问题。正确的做法是用一个 Qt 信号中转定义hotkey_triggered pyqtSignal()在_show_from_hotkey里发信号主线程里连接信号的槽函数再做窗口操作。别忘了用完要keyboard.unhook_all()否则程序退出后热键还会被占用。5. 常见问题与排查技巧实录5.1 双击没反应路径带空格与参数拆分是两大坑我实际使用中最常遇到的情况就是双击一个软件条目后一点反应都没有但是在资源管理器里双击同一个 exe 是能正常启动的。排查到最后绝大多数是路径里带了空格导致的。比如C:\Program Files\SomeTool\tool.exe如果直接在 subprocess.Popen 里传整个字符串会把C:\Program当成一个独立的程序名去查找自然找不到。解决办法如果是单独的路径直接用subprocess.Popen([target])把整个路径作为一个列表元素传入而不是传字符串如果 target 里还带启动参数就必须用shlex.split(target)拆分后再传给 Popen。这个坑在我把参数功能加上之后又踩了一次我用空格直接分割参数结果某个参数里带了个路径路径又有空格直接裂开。最终靠 shlex.split 才彻底解决。5.2 中文乱码与配置损坏编码和原子写一个都不能少Windows 下读写 JSON 配置最大的坑就是编码。如果 json.dump 不显式指定ensure_asciiFalse, encodingutf-8默认会输出一堆\uXXXX转义序列虽然不影响程序读取但手工编辑配置时完全没法看。更糟糕的是如果打开文件用的是系统默认编码 GBK而内容是 UTF-8读出来就是乱码再一保存整个文件就废了。所以我建议每次读写都严格固定格式with open(self.config_path, w, encodingutf-8) as f: json.dump(self.config, f, ensure_asciiFalse, indent2)至于配置损坏前面说过用“临时文件 os.replace”方案。如果已经损坏了我调试时用的方法是先在备份目录里找自动备份的 config.bak 文件没有的话就只能手动修复 JSON 语法。为了降低这种风险我后来给程序加了一个“每次启动成功加载后自动备份一份”的逻辑备份文件保留最近 5 份容量占用也不大但关键时刻真的能救命。Linux 下如果误操作导致配置目录混乱可以直接删除整个配置目录让程序重建rm -rf命令要用得谨慎建议先 mv 成.bak后缀再删给自己留一个反悔的余地。5.3 遇到权限限制或共享文件夹打不开怎么办有段时间我加了几个公司共享盘里的文件夹双击之后报错有的提示“你需要来自 system 的权限才能对此文件夹进行更改”。这个提示其实分两种情况一种是当前 Windows 账户对目标目录只有读取权限没有修改权限这通常要去目标机器的共享权限里加授权另一种是目标目录本身在系统保护位置资源管理器打开没问题但被 os.startfile 调用时触发了 UAC 拦截。针对 UAC 拦截的场景我的处理方案是文件夹和文档类型默认都用explorer.exe的方式去打开即subprocess.Popen([explorer.exe, target])让资源管理器自己去处理权限提升问题程序类型则可以在配置里加一个run_as_admin的布尔字段需要时用shellExecute配合runas操作来提权启动。共享文件夹打不开还有一个很常见的原因就是目标路径写成了本地盘符比如你把共享盘映射成了 Z 盘但换了一台电脑后映射关系不存在了。这种场景用 UNC 路径更稳直接写\\server\share\folder格式不管有没有映射盘符都能访问。配置里要特别注意反斜杠的转义JSON 里写\\server\\share才是安全的标准写法。5.4 假如用 Electron 版拖拽排序怎么实现虽然我的正式版用 PyQt6但开发时我曾经用 Electron 做过一版原型那版里涉及了拖拽排序用的组件就是 vuedraggable。如果你打算参考这个项目做一个 Web 桌面版这里有两条经验可以直接抄。第一条经验是vuedraggable 在处理“跨列表拖拽”时非常顺手直接把两个数组放在 group 属性里对应起来就行。但要留意拖拽后必须同步更新配置文件的顺序字段否则刷新页面又回到原来的排序用户会以为没生效。第二条经验是拖拽过程中最好给目标行加一个高亮 class让用户清楚看到即将插入的位置这个交互反馈在列表删除和重排时非常提升手感不加的话拖拽体验会显得很“木”。不过 Electron 版最终被我放弃了不仅因为打包体积大更因为启动速度比 PyQt6 慢了不少。作为一个工具型应用点开就要立刻能用这个体验上的差距很难靠界面美观弥补。6. 项目的实际使用体验与后续扩展6.1 实际上手两周之后的真实感受这个工具我用到现在已经超过两周最大的感受就是“找东西的时间变成了零”。以前每天开工要依次打开浏览器、截图工具、素材文件夹、后台管理页现在就是按一下热键输入“后”字回车后台管理页直接弹出来。搜索框的全局匹配设计比分类点击还要快因为有时候我根本记不住某个入口属于哪个分类只记得名字里的一两个关键词。有个当时没预料到的好处是因为所有入口都集中在一个列表里我定期整理配置的时候发现了很多“僵尸入口”——装完之后再也没打开过的软件、收藏完就遗忘的网页。顺手删掉之后不仅工具更干净了电脑本身也清爽了一些。这也算是一种“入口梳理带来的数字断舍离”。带来的另一个变化是重装电脑时省事了。以前重装系统要重新装软件、重新配书签、重新建目录结构现在配置文件拷过去路径改一批就完事。虽然还没做到零成本迁移但至少比从零开始整理快得多。6.2 后续想做的几个方向拖拽排序、数据同步、多端共享这个工具目前还有几个明显可以增强的地方。第一个是拖拽排序我现在只能靠编辑 JSON 里的顺序来调整排列体验比较原始。如果后续在 PyQt 里实现我会用 QTableWidget 的 dropEvent 重写记录下拖拽后的行号映射再回写配置。如果是 Electron 版直接用 vuedraggable 就方便多了。第二个是数据同步。我的配置文件现在只存在于本机公司和家里两台机器用不同步。后续打算支持 WebDAV 或 NAS 文件夹同步这样配置文件由系统级同步工具拉取程序只需在启动时检测文件变化后热加载。如果你想自己扩展这块可以把配置文件目录做成一个 Git 仓库GitHub 上建一个私有仓库就能实现版本管理上传整个文件夹时注意保留 JSON 目录结构别把配置文件散到多个地方。第三个是“智能排序”。我在字段里预留的 count 计数后续可以根据打开频次自动把高频入口排到列表顶部甚至可以做一个“最近打开”的动态分类那这个工具就更像一个真正的效率启动器了。如果你有兴趣往这个方向做我建议一开始就把 count 字段加上不然等数据量积累起来再补迁移成本会大很多。最后再分享一个小技巧这个工具可以配成一个开机自启的后台进程启动后不显示窗口只挂一个全局热键真正做到“按一下就出来”。但开机自启要考虑内存占用我目前实测 PyQt6 版本静默驻留大概 60MB 内存在可接受范围内。如果你追求极致轻量可以用纯 Win32 API 或 AutoHotkey 重写一个简化版核心逻辑不变只是开发成本会稍微高一点。工具的本质就是让自己用得顺手技术选型的标准也只有这一条。
返回列表