Qt Undo Framework Demo

Qt Undo Framework Demo

[email protected]

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/View

1. Introduction

在交互应用程序中撤销和重做(Undo/Redo)能力是很重要的。像常见的软件Office,AutoCAD等,有了撤销功能,用户体验更舒服。一般都会使用Command模式来实现这一功能。

命 令模式通过将请求本身变成一个对象来使工具箱对象可向未指定的应用对象提出请求,这个对象可被存储并像其他对象一样被传递。这一模式的关键是一个抽象的 Command类,它定义了一个可执行操作的接口。其最简单的形式是一个抽象的Execute操作。具体的Command子类将接收者作为其一个实例变 量,并实现Execute操作,指定接收者采取动作,而接收者执行该请求所需要的具体信息。在GoF的《Design Patterns》中,给出了Command模式的一般结构,如图1.1所示:

Figure 1.1 Command pattern structure

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录成日志,以及支持可撤销的操作。

支持任意层次的撤销和重做命令的最后一步是定义一个命令历史记录(Command History),或称为已执行的命令列表。从概念上理解,命令的历史记录看起来有如下形状:

Figure 1.2 Command History

每 个圆代表一个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框架,从而写出一个更简单的程序,代码如下所示:

class InsertCommand : public QUndoCommand
{
public:
    InsertCommand(const QModelIndex& theIndex, QStringListModel* theModel);
    ~InsertCommand();

public:
    virtual void undo();
    virtual void redo();

private:
    QModelIndex mIndex;
    QStringListModel* mModel;
};

首先,从QUndoCommand派生出一个插件字符串的类InsertCommand,并要实现undo()和redo()这两个虚函数,实现代码如下所示:

void InsertCommand::undo()
{
    mModel->removeRows(mIndex.row(), 1);
}

void InsertCommand::redo()
{
    mModel->insertRows(mIndex.row(), 1);
    mModel->setData(mIndex, QString("Insert string " + QString::number(mIndex.row())));
}

这样在响应工具栏按钮的函数中,只需要生成这个命令,并将命令加入到命令栈中即可,代码如下:

void undoTest::insertString()
{
    QModelIndex aIndex = mListView->currentIndex();

mUndoStack->push(new InsertCommand(aIndex, mListModel));
}

程序运行效果如下图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

时间: 2024-11-06 04:25:50

Qt Undo Framework Demo的相关文章

Qt Installer Framework翻译(7-6)

工具 Qt Installer Framework包含以下工具: > installerbase > binarycreator > repogen > archivegen > devtool installerbase installerbase工具描述了核心安装程序本身. 所有数据和元信息都将打包到此二进制文件中. 对于安装程序的创建过程,您无需直接调用它. binarycreator 使用binarycreator工具创建离线和在线安装程序. 组件信息和数据将附加到离

Qt Installer Framework的学习(二)

Qt Installer Framework的学习(二) Qt Installer Framework的一些操作可以使用最常见的Qt项目来表示,也就是说,书写pro文件,使用qmake运行之,除了能够编译正常的项目之外,也可以为项目打包.这里最重要的就是binarycreator了.下面就是我命令行使用binarycreator的时候弹出的一些提示,我们可以根据这样的提示,来了解究竟有哪些使用的方法. 上海萌梦信息科技有限公司(微博:http://weibo.com/qtdream)原创文章,首

Qt Installer Framework的学习

Qt Installer Framework是Qt默认包的发布框架.它很方便,使用静态编译Qt制作而成.并且使用了压缩率很高的7z对组件进行压缩.之所以有这些好处,我才觉得值得花一点儿精力研究一下这个框架.从Qt的下载地址中下载Qt Installer Framework,地址是:http://download.qt.io/official_releases/qt-installer-framework/2.0.1/ .下载好了之后点击安装,会将程序以及一些实例安装进来.Qt Installer

使用Qt installer framework制作安装包(不知道是否适合Mac和Linux?)

一.介绍 使用Qt库开发的应用程序,一般有两种发布方式:(1)静态编译发布.这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中.其优势是简单单一,所有的依赖库都集中在一起,其缺点也很明显,可执行程序体量较大,光Qt核心库加起来就得十多兆.(2)制作安装包发布.这种方式的原理也简单,就是将可执行程序和其依赖的库文件一起打包压缩,制作成安装包发布.制作安装包的工具挺多,今天要说的是Qt官方的安装包制作框架Qt installer framework.这个框架由Qt官方出品,广泛应用

Qt Installer Framework的学习(三)

Qt Installer Framework的学习(三) Qt Installer Framework的样例中.通常是这种:config目录一般放了一个config.xml文件,包括的是安装配置xml的内容.packages包括的是须要安装的包的内容.普通情况不止一个安装包,每个安装包也不止是一个文件,那么每个包都有目录,里面的目录中有data以及meta子目录. data目录中是安装包的内容,meta目录中是package.xml文件.这个文件包括的是安装包的安装配置内容.另一些项目包括的是p

使用Qt installer framework制作安装包

一.介绍 使用Qt库开发的应用程序,一般有两种发布方式:(1)静态编译发布.这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中.其优势是简单单一,所有的依赖库都集中在一起,其缺点也很明显,可执行程序体量较大,光Qt核心库加起来就得十多兆.(2)制作安装包发布.这种方式的原理也简单,就是将可执行程序和其依赖的库文件一起打包压缩,制作成安装包发布.制作安装包的工具挺多,今天要说的是Qt官方的安装包制作框架Qt installer framework.这个框架由Qt官方出品,广泛应用

qt: qt install framework使用问题;

qt提供了qt install framework用于程序打包,方便.快捷,并且可以对界面和功能进行自定义. 但是, 如果使用默认的打包配置,不进行安装页面功能自定义的话, 在修改安装路径时,在对程序进行卸载的时候,会将安装路径下的所有文件 全部删除. 那么,这就会导致一个问题: 如果用户修改了安装路径,没有新建文件夹用来安装,而是直接安装在了D:\目录下,在卸载的时候,会将 D:\下的所有文件全部清除掉.很操蛋的操作! 参考: https://stackoverflow.com/questio

Qt Installer Framework Manual 问题之一

出现错误:This application failed to start because it could not find or load the Qt platform plugin 在使用 windeployqt 打包程序之后,然后使用 binarycreator 生成安装程序的过程中,要保证安装之后的目录结构和 打包程序的目录结构一致,否则也可能会出现如上所述错误,导致程序无法正常运行. 方法是: 1. 如果打包的目录中你看到的是一个文件夹,把这个文件夹看作是一个模块,直接放入 dat

Qt Installer Framework翻译(5-4)

自定义安装程序 您可以使用脚本通过以下方式来自定义安装程序: > 添加Qt Installer Framework操作,该操作由脚本提供,并由安装程序执行. > 添加新页面,该页面由您在package.xml文件中指定,并将其放置在packages文件夹中. > 修改现有页面,通过插入自定义用户界面元素来作为子部件. > 添加语言变体. 您可以同时使用组件脚本和控制脚本来自定义安装程序.通过在组件的package.xml文件的Script元素中指定组件脚本,可以将该脚本与特定的组件