LabVIEW VI Scripting 实现撤销/重做功能深度报告
1. 引言
在 LabVIEW 开发环境中,VI Scripting 提供了一种强大的能力,允许开发者通过编程方式创建、编辑和检查 VI。这极大地提高了自动化和工具开发的效率。然而,与任何编辑操作一样,通过脚本进行的修改也存在误操作的风险。因此,实现一个健壮的撤销(Undo)和重做(Redo)功能对于提升用户体验和确保操作的可恢复性至关重要。
您的需求涵盖了通过 VI Scripting 对目标 VI 进行的多种具体操作(添加/删除对象、修改属性、连线、调整大小等)的撤销,同时也包括针对运行 VI Scripting 工具本身的编辑操作的撤销。此外,您需要支持单步和多步撤销,并包含重做功能,目标 LabVIEW 版本为 2015 或 2022。
本报告将基于我们之前的研究成果,详细阐述在 LabVIEW 中使用 VI Scripting 实现这些功能的关键技术、挑战和潜在解决方案。
2. LabVIEW VI Scripting 的原生撤销/重做机制
LabVIEW VI Scripting 提供了一套原生的机制来支持脚本操作的撤销和重做,这主要通过 Transaction
相关的方法实现。
2.1 Transaction 方法详解
核心在于使用 Transaction.Begin Undo
、Transaction.End Undo
和 Transaction.Fail
这三个方法来包装您的脚本操作。
-
Transaction.Begin Undo
:-
在您开始执行一系列希望能够被撤销的脚本操作之前调用。
-
它接受一个
Name
输入参数。这个字符串将显示在 LabVIEW 编辑器的 "编辑" 菜单中的 "撤销" 和 "重做" 选项旁边(例如,"撤销 添加对象")。这为用户提供了清晰的操作描述。 -
调用此方法标志着一个可撤销事务的开始。
-
-
Transaction.End Undo
:-
在您的脚本代码成功执行,并且确实对目标 VI 进行了实质性更改(例如,添加了对象、修改了属性等)之后调用。
-
调用此方法会将当前事务中的所有脚本操作提交到目标 VI 的撤销堆栈中。
-
成功提交后,LabVIEW 的 "编辑" 菜单中将出现对应的 "撤销 [Name]" 选项。
-
-
Transaction.Fail
:-
如果在脚本执行过程中发生错误,或者您的脚本代码在执行后发现实际上没有对目标 VI 进行任何更改,则应调用此方法。
-
调用此方法会中止当前的事务,并且不会将任何操作提交到目标 VI 的撤销堆栈。
-
"编辑" 菜单中也不会出现新的 "撤销" 选项。
-
2.2 不使用 Transaction 方法的后果
研究表明,如果不使用这些 Transaction
方法来包装您的脚本操作,将会产生两个严重后果:
-
用户无法撤销脚本操作: 通过未包装的脚本执行的更改将无法通过 LabVIEW 的标准撤销功能回退。
-
可能清除现有撤销堆栈: 未包装的脚本操作可能会意外地清除目标 VI 当前的撤销历史记录,导致用户无法撤销之前在 LabVIEW 编辑器中手动执行的操作。
因此,对于任何旨在集成到 LabVIEW 编辑器工作流程中的 VI Scripting 工具,正确使用 Transaction
方法是实现基本撤销功能的基础。
2.3 程序化控制撤销/重做
除了通过菜单操作,VI Scripting 还提供了程序化地触发撤销和重做的方法:
-
VI:Transaction:Undo
: 对应于执行一次撤销操作,类似于选择 "编辑" -> "撤销"。 -
VI:Transaction:Redo
: 对应于执行一次重做操作,类似于选择 "编辑" -> "重做"。 -
VI:Transaction:Fail
: 对应于中止当前事务,类似于调用Transaction.Fail
方法。
这些方法允许您在脚本工具自身的 UI 中集成撤销/重做按钮,或者在特定逻辑分支中控制撤销流程。
3. 针对特定 VI Scripting 操作的撤销实现
实现对添加/删除对象、修改属性、连线、调整大小等具体操作的撤销,需要针对每种操作类型,在执行前捕获必要的状态信息,并在撤销时利用这些信息恢复到之前的状态。
3.1 添加对象 (Add Object)
-
操作: 使用
New VI Object
函数向前面板或程序框图添加控件、指示器、结构、函数等。 -
撤销实现:
-
在
Transaction.Begin Undo
之后,执行添加对象的脚本。 -
为了撤销此操作,需要能够删除刚刚添加的对象。
-
记录信息: 在添加对象后,需要获取新创建对象的引用。这个引用是执行删除操作的关键。同时,记录对象的类型(例如,Numeric Control, While Loop)和其所有者(例如,Block Diagram, Front Panel, 一个特定的结构)。
-
撤销逻辑: 当用户执行撤销时,通过之前记录的对象引用,调用
Generic:Delete
方法删除该对象。 -
-