Abstract. Qt’s Undo Framework is an implementation of the Command Pattern, for implementing undo/redo functionality in applications. The Command pattern is based on the idea that all editing in an application is done by creating instances of command objects. Command objects apply changes to the document and are stored on a command stack. Furthermore, each command knows how to undo its changes to bring the document back to its previous state. As long as the application only uses command objects to change the state of the document, it is possible to undo a sequence of commands by traversing the stack downwards and calling undo on each command in turn. It is also possible to redo a sequence of commands by traversing the stack upwards and calling redo on each command. 设计模式
Key Words. Qt, Undo/Redo, Command Pattern, Model/Viewapp
1. Introduction 框架
在交互应用程序中撤销和重作(Undo/Redo)能力是很重要的。像常见的软件Office,AutoCAD等,有了撤销功能,用户体验更舒服。通常都会使用Command模式来实现这一功能。ide
命 令模式经过将请求自己变成一个对象来使工具箱对象可向未指定的应用对象提出请求,这个对象可被存储并像其余对象同样被传递。这一模式的关键是一个抽象的 Command类,它定义了一个可执行操做的接口。其最简单的形式是一个抽象的Execute操做。具体的Command子类将接收者做为其一个实例变 量,并实现Execute操做,指定接收者采起动做,而接收者执行该请求所须要的具体信息。在GoF的《Design Patterns》中,给出了Command模式的通常结构,如图1.1所示:函数
Figure 1.1 Command pattern structure工具
将一个请求封装为一个对象,从而使你可用不一样的请求对客户进行参数化;对请求排队或记录成日志,以及支持可撤销的操做。post
支持任意层次的撤销和重作命令的最后一步是定义一个命令历史记录(Command History),或称为已执行的命令列表。从概念上理解,命令的历史记录看起来有以下形状:学习
Figure 1.2 Command Historyidea
每 个圆表明一个Command对象,标有present的对象即为当前命令对象。当咱们调用Unexecute()后,标有present的对象将会向左 移;当调用Execute(),标有present的对象将会向右移。重复这个过程,咱们能够进行多层次的撤销,层次数只受命令历史记录长度的限制。
在Qt的Undo框架中主要包括如下几个类:
v QUndoCommand:这个类至关于Command模式中的那个抽象基类Command,全部这些命令都被保存到undo栈中,在其派生类中实现undo和redo函数。
v QUndoStack:这个至关于命令历史记录,其中保存了Command对象的列表。
v QUndoGroup:是一个undo stack的组合。
v QUndoView:是显示undo堆栈中内容的一个列表组件,在这个视图中点击命令的名称也能够实现与Undo/Redo按钮相同的做用。
本文经过一个简单的例子来示例Qt中Undo框架,先在简单的List模型中实现,进而在Tree上实现。掌握Qt的这个框架,就能够不用OpenCASCADE的OCAF了,而且Qt的代码用起来仍是相对简单清晰的。
2.Example
Qt提供了一个Undo框架的示例,程序还涉及到图形绘制相关的内容,程序效果以下图2.1所示:
Figure 2.1 Qt Undo Framework Example
结合这个示例程序,学习一下Qt的Undo框架,从而写出一个更简单的程序,代码以下所示:
首先,从QUndoCommand派生出一个插件字符串的类InsertCommand,并要实现undo()和redo()这两个虚函数,实现代码以下所示:
这样在响应工具栏按钮的函数中,只须要生成这个命令,并将命令加入到命令栈中便可,代码以下:
程序运行效果以下图2.2所示:
Figure 2.3 Test Qt Undo Framework
经过工具栏上的undo/redo及命令列表中选择,均可以实现命令的回退及重作。完整的程序代码可经过文后连接下载。
3.Conclusion
在 学习C++基本语法后,能够看看GoF的《设计模式》。刚刚接触可能感受有些抽象,这时能够使用Qt来编写一些程序来练练手。用Qt来编程感受比MFC要 舒服不少,有些类封装得很直接,易于使用。尽管MFC中也有个Document/View的设计模式,可是Qt中的MVC用起来更直接。经过使用现有的框 架,来理解那些抽象的设计模式,从而加深面向对象的观念,让本身的程序更简单,有趣。
OpenCASCADE的OCAF框架也提供了一个 数据框架,基于这个树形的框架,能够存储层次表示的数据,且也提供了Undo/Redo的支持。基于OCAF框架,能够快速开发出必定功能的专业软件了。 可是要使用OCAF框架,涉及的OpenCASCADE库不少。若是打算开发一个轻量级的三维程序,而又正好选择了Qt来开发GUI,这时就能够考虑使用 Qt的MVC框架及在这个框架上的Undo/Redo功能,这样开发效率能够相对高一些,且程序发布时依赖的动态库也要少不少。
流行的工 厂设计软件中的数据框架多用树形结构,树中每一个结点上的属性可让用户自由扩展,像OCAF中经过TDataStd_Integer添加一些整数属性一 样,及用TDataStd_Name添加名称属性。可是OCAF中添加属性有些局限性,由于每种属性是用GUID来区别的,因此每一个结点上同一种属性只能 有一个。
因此用Qt的MVC框架来根据须要实现一个自定义的树形Model,再基于V3d_Viewer实现一个显示三维的View,便可以实现一个简单,但看上去相对专业的CAD建模程序了。
4. References
1. GoF. Design Patterns-Elements of Reusable Object-Oriented Software.机械工业出版社. 2010
2. Qt5.4. Overview of Qt’s Undo Framework. 2014
3. Qt5.4. Undo Framework Example. 2014
4. OpenCASCADE6.8.0. OCAF. 2014
5. OpenCASCADE6.8.0. OCAF White Paper. 2014
6. OpenCASCADE6.8.0. Distribution of Data Through OCAF Tree. 2014
PDF Version and Source code: Qt Undo Framework Demo