HG-ha/MTools快速上手:内置插件系统开发指南——30行Python扩展新功能
1. 开箱即用:第一眼就爱上这个工具
HG-ha/MTools 不是那种装完还要折腾半天配置的工具。你下载安装后双击启动,界面干净、响应迅速、图标清晰,没有广告弹窗,也没有强制登录——它就是为你干活而生的。
它不像传统工具箱那样把一堆功能塞进一个窗口里让人找不着北,而是用现代桌面应用的设计逻辑组织功能:左侧导航栏分类明确,中间工作区专注当前任务,右上角一键切换深色/浅色模式。打开后你不需要看说明书就能猜到“图片处理”点进去能裁剪、调色、批量重命名,“AI 工具”里能一键识图、语音转文字、生成文案,“开发辅助”则藏着 JSON 格式化、正则测试、时间戳转换这些程序员天天用的小帮手。
更关键的是,它不挑设备。你在 Windows 笔记本上用 NVIDIA 显卡跑 AI 去背,速度飞快;在 MacBook Air M2 上处理一段 1080p 视频,风扇几乎不转;在 Linux 服务器上通过远程桌面调用图像增强功能,也稳稳当当。这不是“能跑”,而是“跑得舒服”。
它不靠堆砌功能取胜,而是让每个功能都真正可用、可依赖。比如你拖一张商品图进去,点击“智能抠图”,2 秒出透明背景 PNG;再点“一键生成多尺寸缩略图”,自动输出 1920×1080、720×480、320×240 三套,连文件名都按规则帮你起好。这种“做完就走”的体验,才是现代工具该有的样子。
2. 插件系统:你的需求,不用等更新
MTools 的核心魅力之一,是它把“扩展性”做进了骨子里——不是靠开放 API 让你写客户端调用,而是直接支持本地 Python 插件热加载。这意味着:
- 你不用改源码、不用编译、不用提交 PR;
- 写个
.py文件丢进plugins/目录,重启软件(或点一下刷新按钮),新功能就出现在菜单里; - 所有插件共享主程序的 GPU 加速能力、UI 组件库和状态管理;
- 它甚至自带插件模板、调试日志、错误捕获机制,写崩了也不会卡死主程序。
这背后不是简单的importlib动态导入,而是一套轻量但完整的插件生命周期管理:从加载、初始化、UI 注册、事件绑定,到卸载清理,全部封装成几个清晰接口。你只需要关注“我想做什么”,而不是“怎么让代码被识别”。
举个最实在的例子:团队里设计师总要给截图加统一水印,但 MTools 默认没这个功能。以前得等开发者排期、发版本、大家更新……现在?你花 5 分钟写个watermark.py,放进插件目录,所有人下次打开就能用——连重启都不用,因为插件支持热重载。
这才是真正属于用户自己的工具。
3. 30 行代码,写一个真实可用的插件
我们来动手写一个完整、可运行、带 UI 的插件:“文本行号添加器”——把一段粘贴的代码或日志,自动加上左侧行号(如1 | ...),方便协作时快速定位问题。
这个插件会:
- 在右键菜单中增加“添加行号”选项;
- 支持选中文本或全文处理;
- 输出带行号的新文本,自动复制到剪贴板;
- 错误时友好提示,不中断主程序。
# plugins/line_number.py from mtools.plugin import PluginBase, register_plugin from mtools.ui import show_message, get_selected_text, set_clipboard_text class LineNumberPlugin(PluginBase): def __init__(self): super().__init__() self.name = "文本行号添加器" self.description = "为选中或全部文本添加左侧行号(1 | ...)" def on_context_menu(self, text: str) -> list: # 右键菜单项 return ["添加行号"] def on_context_action(self, action: str, text: str) -> str: if action != "添加行号": return text if not text.strip(): show_message(" 请先选中一段文本,或确保编辑区有内容", "提示") return text try: lines = text.splitlines() numbered = [f"{i+1} | {line}" for i, line in enumerate(lines)] result = "\n".join(numbered) set_clipboard_text(result) show_message(f" 已添加 {len(lines)} 行行号,结果已复制到剪贴板", "完成") return result except Exception as e: show_message(f"❌ 处理失败:{str(e)}", "错误") return text # 必须调用此函数注册插件 register_plugin(LineNumberPlugin())就这么 30 行(含空行和注释),你已经完成了一个具备生产可用性的插件:
- 第 1 行导入核心模块,
mtools.plugin是插件基类,mtools.ui提供 UI 交互能力; on_context_menu()返回右键菜单显示的文字,这里只返回一个字符串;on_context_action()是实际执行逻辑,接收当前文本和点击的菜单项,返回处理后的新文本;show_message()弹出友好提示,set_clipboard_text()自动复制结果,所有这些都已封装好,你不用管平台差异;- 最后一行
register_plugin(...)是必须的“注册声明”,告诉 MTools:“这个类是个插件,请加载它”。
保存为plugins/line_number.py,重启 MTools(或在设置里点“重载插件”),随便打开一个文本框,右键——“添加行号”就出现了。选几行代码试试,瞬间生成带编号的文本,粘贴到群里,同事一眼就能说“第 5 行那个变量名拼错了”。
没有构建步骤,没有依赖管理,没有环境隔离。你写的,就是它运行的。
4. 插件开发进阶:不只是“加功能”
写一个菜单项只是起点。MTools 的插件系统真正强大之处,在于它允许你深度融入主程序的工作流。我们来看几个高频实用场景的实现思路,全部基于公开接口,无需修改主程序代码。
4.1 在主工具栏添加自定义按钮
有些功能你希望常驻界面,而不是藏在右键里。比如你经常要用“JSON 格式化 + 美化缩进”,可以加个按钮:
def on_toolbar_init(self, toolbar): from PyQt6.QtWidgets import QPushButton btn = QPushButton(" JSON 美化") btn.clicked.connect(self._format_json) toolbar.addWidget(btn) def _format_json(self): text = get_selected_text() or "" if not text.strip(): show_message("请先选中 JSON 文本", "提示") return try: import json obj = json.loads(text) pretty = json.dumps(obj, indent=2, ensure_ascii=False) set_clipboard_text(pretty) show_message(" JSON 已美化并复制", "完成") except Exception as e: show_message(f"❌ JSON 格式错误:{e}", "错误")只需在插件类中定义on_toolbar_init()方法,MTools 就会在主工具栏创建空间并传入toolbar对象,你往里塞任何 Qt 控件都行。
4.2 监听文件拖入事件,自动触发处理
设计师拖一张 PNG 进来,你想自动转成 WebP 并压缩到 80% 质量:
def on_file_dropped(self, file_path: str): if file_path.lower().endswith(('.png', '.jpg', '.jpeg')): from PIL import Image img = Image.open(file_path) webp_path = file_path.rsplit('.', 1)[0] + '.webp' img.save(webp_path, 'WEBP', quality=80) show_message(f" 已保存为 {webp_path}", "完成") return webp_path # 返回新路径,主程序可继续处理 return None只要实现on_file_dropped(),MTools 就会在用户拖放文件时调用它,并把处理后的路径反馈给主流程(比如自动在图片查看器中打开新文件)。
4.3 创建独立面板,承载复杂交互
比如你要集成一个“正则表达式实时测试器”,需要输入框、测试文本、匹配高亮、分组提取——这时右键菜单就不够用了。MTools 支持插件注册独立 Tab 面板:
def on_panel_init(self, tab_widget): from PyQt6.QtWidgets import QWidget, QVBoxLayout, QTextEdit panel = QWidget() layout = QVBoxLayout(panel) layout.addWidget(QTextEdit("正则测试器 —— 输入 pattern 和 text 即可实时匹配")) tab_widget.addTab(panel, " 正则测试")调用tab_widget.addTab(),你的 UI 就会出现在主窗口顶部 Tab 栏中,和其他原生功能完全一致。
这些能力不是“未来计划”,而是当前版本已稳定支持的接口。你不需要成为 Qt 专家,也不用研究信号槽机制——所有底层桥接、线程安全、资源释放,MTools 都替你兜底了。
5. 插件发布与协作:小团队也能共建生态
单人写插件很酷,但真正让工具长青的,是可持续的协作机制。MTools 为此设计了一套极简但有效的插件分发方案。
5.1 插件打包:一个 ZIP 就是完整应用
你写好my_tool.py,还附带了图标icon.png和说明README.md,只需把它们放进同一文件夹,压缩为my_tool.zip。用户下载后,双击 ZIP 文件,MTools 会自动解压到plugins/下对应子目录,并立即启用。
ZIP 包内结构自由,支持子文件夹、资源文件、额外 Python 模块(如requests)。MTools 会自动将插件目录加入sys.path,所以import my_utils完全合法。
5.2 插件市场:免审核、零门槛、纯静态
MTools 官方维护一个公开的插件索引页(https://mtools.dev/plugins),但它不是中心化应用商店。它只是一个 JSON 文件:
[ { "id": "line-number", "name": "文本行号添加器", "author": "社区用户", "version": "1.0.0", "url": "https://github.com/mtools-plugins/line-number/releases/download/v1.0.0/line-number.zip", "description": "为代码或日志添加左侧行号,支持一键复制" } ]任何人只要提交一个符合格式的 PR 到 GitHub 仓库,就能把自己的插件加入索引。没有人工审核,没有分成抽成,没有上架费。MTools 启动时自动拉取这个 JSON,用户在“插件市场”里看到的就是最新列表。
5.3 团队私有插件库:三行配置搞定
如果你在公司内部使用,不想公开插件,只需在config.yaml中加三行:
plugin_sources: - name: "设计部工具集" url: "https://intra.example.com/mtools/plugins.json" - name: "研发组增强包" url: "https://gitlab.example.com/dev-tools/mtools-plugins.json"MTools 会合并所有来源的插件列表,统一展示。IT 部门维护一个内部 JSON,每次发版只需更新链接指向的文件,全公司员工打开软件就能看到新插件。
这既保障了安全性,又保留了开源协作的敏捷性。你不需要运维服务器,不需要写后台,甚至不需要懂 Web 开发——一个静态 JSON 文件,就是你的插件生态。
6. 总结:工具的终极形态,是让你忘记它存在
HG-ha/MTools 的插件系统,不是为了炫技,也不是为了标榜“可扩展”。它是对一个朴素问题的回答:当用户遇到一个新需求,最快多久能用上?
答案是:从你想到这个点子,到它出现在菜单里,整个过程可以控制在 10 分钟内——5 分钟写代码,2 分钟测试,3 分钟发给同事。
它不强迫你学新框架,不绑架你用特定语言,不设限你的创意边界。你用 Python 写,它就运行;你调用 OpenCV,它就加速;你嵌入一个小型 LLM 推理,它就分配 GPU 显存。它像空气一样透明,只在你需要时提供支撑。
更重要的是,它把“工具开发权”交还给了真实使用者。设计师写一个批量加水印脚本,运营写一个社媒文案生成器,测试工程师写一个日志关键词高亮插件……这些都不是“开发需求”,而是他们每天工作的自然延伸。
MTools 不是终点,而是一个支点。你写的每一行插件代码,都在把这个支点撬得更高一点——直到某天,你发现自己不再需要“另一个工具”,因为你已经拥有了一个完全适配自己工作流的、活的、不断生长的数字工作台。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。