发布时间:2026/8/17 19:41:03
零基础开发 Xournal++ Lua 插件:3 个实战示例带你实现笔记自动化 零基础开发 Xournal Lua 插件3 个实战示例带你实现笔记自动化【免费下载链接】xournalppXournal is a handwriting notetaking software with PDF annotation support. Written in C with GTK3, supporting Linux (e.g. Ubuntu, Debian, Arch, SUSE), macOS and Windows 10. Supports pen input from devices such as Wacom Tablets.项目地址: https://gitcode.com/gh_mirrors/xo/xournalppXournal 是一款基于 C 与 GTK3 的开源手写笔记软件支持 PDF 标注、压感笔输入横跨 Linux、macOS 与 Windows 三大平台。本文面向想扩展笔记工作流的开发者通过 3 个可直接运行的示例带你从认识插件目录结构开始逐步掌握app.registerUi、app.changeActionState等核心 API最终把一键切换网格纸循环换色这类操作变成你自己的脚本真正让手写笔记告别重复劳动。为什么要给手写笔记软件写插件用 Xournal 记笔记久了你会发现一个规律反复在做的事就那么几件。上课前要把页面切成网格纸、写重点时想快速换一支红色笔、演示时要隐藏工具栏。这些操作虽然都藏在菜单里但每做一次就要点两三下一天下来浪费的时间不少。Xournal 的插件系统正是为解决这类高频重复操作而生的。它不要求你懂 C也不要求重新编译整个项目——插件就是一个普通的目录里面放一个plugin.ini配置文件和若干个 Lua 脚本。软件启动时会把所有插件目录扫描出来你可以在插件管理器中一键启用之后就能在菜单栏直接点到自己写的功能按钮。先认识一个插件的身份证plugin.ini每个插件目录的入口是plugin.ini它负责告诉 Xournal 三件事这个插件是谁写的、默认是否启用、主脚本叫什么。以项目自带的示例插件为例见plugins/Example/plugin.ini[about] authorAndreas Butti descriptionThis is a minimal example plugin, for reference versionxournalpp [default] enabledfalse [plugin] mainfilemain.lua拆开看三个小节[about]作者、描述、版本号。versionxournalpp表示跟随软件版本你也可以写死如1.0。[default]enabledfalse表示插件安装后默认关闭需要你在插件管理器里手动打开。[plugin]mainfilemain.lua指定主脚本文件名Xournal 启动时会加载它。插件放在哪里有两条搜索路径软件安装目录下的../plugins以及你的配置目录中的plugins子目录个人目录优先级更高适合放自己写的插件。插件管理器界面菜单插件 管理插件就是扫描这两个目录得到的列表其扫描与启用逻辑可以在src/core/plugin/PluginController.cpp中看到。插件的心脏initUi 与注册回调配置好plugin.ini之后真正干活的是 Lua 脚本。Xournal 用一个全局对象app向脚本暴露全部功能而脚本里最先被执行的是一个约定函数initUi()。程序在初始化阶段会检查这个函数是否存在并调用它对应源码src/core/plugin/Plugin.cpp中的registerToolbar逻辑你的 UI 注册代码必须放在这里面。来看最简写法复制plugins/Example/main.lua-- 初始化注册菜单项 function initUi() app.registerUi({ [menu] Test123, [callback] exampleCallback, [accelerator] Controlt }) end -- 点击菜单后触发 function exampleCallback() app.openDialog(Test123, {Yes, No}, dialogCallback) end -- 用户点击对话框按钮后触发 function dialogCallback(result) print(result .. result) end关键点有三个app.registerUi只能在initUi里调用它把菜单项挂到插件菜单下。menu是显示名称callback是点击后要执行的函数名accelerator可选用来绑定快捷键。回调函数名要与注册字符串完全一致Xournal 通过名字在脚本里查找并调用它们。app.openDialog的第三个参数是回调函数名按钮编号会作为参数传给它。实战一给当前页面一键切换网格纸最典型的需求是换页面背景。项目自带的plugins/ToggleGrid/togglegrid.lua给出了教科书级的实现——用一个布尔变量记录当前状态来回切换网格纸与空白纸function initUi() app.registerUi({[menu] Toggle Grid Paper, [callback] toggleGridPaper}) end local toggleState false function toggleGridPaper() if toggleState true then app.changeActionState(grid-snapping, true) app.changeCurrentPageBackground(graph) else app.changeActionState(grid-snapping, false) app.changeCurrentPageBackground(plain) end toggleState not toggleState end这段代码引入两个高频 APIapp.changeActionState(action, state)修改界面动作的状态这里把网格吸附开关也一并联动保证画线时自动对齐网格。动作名如grid-snapping、zoom、tool-color完整清单见plugins/luapi_application.def.lua中的 Action 列表。app.changeCurrentPageBackground(graph)把当前页背景切换为网格纸其他取值还有plain空白、lined横线、ruled方格等。避坑提示涉及枚举类型的动作如工具类型、笔迹粗细不要硬编码数字要使用app.C常量表例如app.C.Tool_pen这样能兼容未来版本变化。实战二3 步实现循环换色笔第二个场景来自plugins/ColorCycle/main.lua演示课想连续换红、蓝、绿几支笔的颜色手动点色板太慢不如写个循环切换。它的思路是准备一张颜色表 → 维护一个当前索引 → 每次触发把索引往后挪一位 → 通过app.changeToolColor应用到当前工具function initUi() app.registerUi({[menu] Cycle through color list, [callback] cycle, [accelerator] Altc}) end local colorList { {black, 0x000000}, {red, 0xff0000}, {blue, 0x3333cc}, {green, 0x008000}, {yellow, 0xffff00} } local currentColor 0 function cycle() currentColor currentColor % #colorList 1 -- 应用到当前工具并同步改选中元素的颜色 app.changeToolColor({[color] colorList[currentColor][2], [selection] true}) end与changeActionState不同app.changeToolColor接收的是参数表而非两个位置参数。表里color是 0xRRGGBB 格式的颜色值selectiontrue表示同时把当前选区里的元素也染成新颜色如果只想改笔的颜色则传[tool] pen即可。这个示例还展示了插件的状态保持特性脚本里的局部变量currentColor在两次调用之间是保留下来的所以你可以用 Lua 变量记录插件的运行状态而无需写配置文件。进阶玩法不止于点菜单的自动化上面两个示例都是手动触发但插件 API 的能力远不止此。细读plugins/luapi_application.def.lua这是官方 API 参考文档每个函数都有完整签名与示例你会发现整套文档操作都对你开放批量写入内容app.addStrokes按坐标数组批量画笔画app.addTexts在指定坐标插入文本框app.addImages把本地图片贴进页面均支持allowUndoRedoAction参数individual/grouped/none控制撤销粒度。读取文档结构app.getStrokes(all)返回全文档所有笔迹的坐标、宽度、颜色app.getDocumentStructure()返回每一页的尺寸、图层与背景信息。导出与打开app.export支持把当前文档导出为 PDF、SVG 或 PNGapp.openFile可以代开本地文件并滚动到指定页。工具栏自定义app.registerUi还能注册工具栏图标传toolbarId在工具栏自定义对话框里把Plugin::你的ID拖到工具栏上就能得到一个专属按钮。这些能力组合起来可以做出很实用的工具比如写一个对选中笔迹统一重新着色的批处理、一个一键把当前页导出为图片的快捷导出甚至一个在每页固定位置插入日期文本框的批注工具。参考plugins/目录下其他自带插件Export、FitToContent、LayerActions等的写法能更快上手。开发调试避坑清单把容易踩的坑集中列出来帮你少走弯路改了脚本必须重启生效initUi只在启动时执行一次没有热重载机制。改完代码重启软件才能看到变化。注意回调函数的命名约定registerUi传的callback、openDialog传的第三个参数都是函数名字符串函数必须定义在全局作用域不能定义在local里。插件没出现在菜单里先查两个位置一是插件管理器里是否已启用[default] enabledtrue或手动勾选二是plugin.ini的[plugin]段mainfile文件名是否与脚本文件名完全一致。调试输出用print脚本里的print会打到程序日志中运行软件时用命令行启动如xournalpp直接运行即可看到输出这是最直接的排查手段。枚举值一律走app.C常量不要手写魔法数字去匹配工具类型或线宽档位版本升级后数字可能变化。文件路径用app.getFolder需要读写配置或缓存文件时用app.getFolder(config)/(state)获取专属目录它会自动创建避免污染用户目录。动手练一练把它变成你的第一个插件从头梳理一遍完整流程照着做你就能拥有自己的插件创建目录plugins/下手放一个文件夹比如my-first-plugin/。写入plugin.iniabout段填作者信息plugin段mainfilemain.lua。编写main.lua定义initUi并调用app.registerUi再实现对应的回调函数。启动 Xournal打开插件管理器启用它回到菜单插件下找到你的菜单项试试。Xournal 的插件体系把文档读取、笔迹绘制、UI 注册、文件导出全部封装成了几十个 Lua 函数学习门槛远比想象中低——你今天就能写出第一个一键切换网格纸下一步完全可以挑战批量导出所有页为图片这类自动化脚本。把重复劳动交给脚本把时间留给真正的笔记内容。【免费下载链接】xournalppXournal is a handwriting notetaking software with PDF annotation support. Written in C with GTK3, supporting Linux (e.g. Ubuntu, Debian, Arch, SUSE), macOS and Windows 10. Supports pen input from devices such as Wacom Tablets.项目地址: https://gitcode.com/gh_mirrors/xo/xournalpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/8/17 19:41:03

ACTH (1-14) ;SYSMEHFRWGKPVG

一、基础信息中文名称:促肾上腺皮质激素片段 (1-14)三字母序列:Ser-Tyr-Ser-Met-Glu-His-Phe-Arg-Trp-Gly-Lys-Pro-Val-Gly单字母序列:SYSMEHFRWGKPVG修饰说明:无末端修饰、无二硫键分子式:C77H109N21O20S分子量&#…

2026/8/17 19:41:03

HEIC缩略图插件免费方案:3步让Windows直接预览iPhone照片

HEIC缩略图插件免费方案:3步让Windows直接预览iPhone照片 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC/HEIF files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 你有没有经…

2026/8/17 20:51:18

轮胎建模仿真全流程与Abaqus实战技巧

1. 轮胎建模仿真项目概述第一次接触轮胎建模仿真时,我也被那些复杂的参数和物理方程吓到过。但真正上手后发现,只要掌握正确的拆解方法,这个过程确实像搭乐高积木一样有趣。今天我要分享的这套建模流程,已经在我们团队内部验证过二…

2026/8/17 20:51:18

AI视频生成生态构建:从模型优化到工程落地的实战指南

这次我们来看一个关于AI视频生成领域竞争格局的深度分析。标题“中国为何赢下AI视频竞赛:生态而非模型”直接点出了一个核心观点:在AI视频这场全球技术角逐中,中国的优势可能不在于单一模型算法的绝对领先,而在于其构建的完整应用…

2026/8/17 20:51:18

Conda虚拟环境全攻略:从依赖隔离到团队协作的Python环境管理

1. 项目概述:为什么我们需要Conda虚拟环境?如果你在Python世界里摸爬滚打过一阵子,大概率会遇到过这样的场景:项目A需要TensorFlow 1.x,项目B却要求TensorFlow 2.x;或者你刚在一个环境里装好了某个库的特定…

2026/8/17 20:46:17

智能体互联网中技能描述欺骗攻击的攻防实战与防御体系构建

1. 从一次“完美”的任务分配失败说起 想象一下,你正在管理一个由数十个AI智能体组成的协作网络,我们称之为“智能体互联网”。在这个网络里,每个智能体都像一名身怀绝技的专家,它们将自己的“技能描述”注册到一个中央任务路由中…

2026/8/17 10:49:52

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/17 5:02:51

工业传感器与变送器详解:序章 从物理世界到工业数据

序章 从物理世界到工业数据 ——重新认识工业传感器与变送器 工业自动化系统正变得日益复杂。今天的工业现场早已不是简单的控制回路,而是由多层技术共同构成的立体体系:PLC、DCS、SCADA、MES、工业互联网、边缘计算与人工智能。控制系统可以执行复杂算法,工业网络可以实现…

2026/8/17 0:02:57

LabVIEW异步调用实战:解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必经之路如果你在LabVIEW里写过稍微复杂点的程序,尤其是涉及到界面响应、多任务并行或者硬件IO等待,大概率会遇到一个头疼的问题:程序“卡”住了。前面板点不动,进度条不更新…

2026/8/17 0:02:57

飞书局域网文件传输实战:3种方案实现高速点对点传输

1. 项目概述:为什么要在局域网内用飞书传文件? 飞书作为一款主流的协同办公套件,其核心功能是围绕云端协作设计的。无论是文档、表格还是文件,通常的分享逻辑都是“上传到云端 -> 生成链接 -> 分享给同事”。这个流程在互联…

2026/8/17 15:07:41

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/17 17:27:06

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/15 9:46:30

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…