用到的类:

1.QUndoStack: 一个存放 QUndoCommand 命令的栈.
2.QUndoCommand:The QUndoCommand class is the base class of all commands stored on a QUndoStack.
3.QUndoView:The QUndoView class displays the contents of a QUndoStack.(显示QUndoStack的内容)

下面的例子是根据 Qt 自带的例子(undoframework)写的:

重写 QGraphicsPolygonItem (方块)

myitem.h

#ifndef MYITEM_H
#define MYITEM_H#include <QGraphicsItem>class myItem :public QGraphicsPolygonItem
{public:enum {Type = UserType +1};explicit myItem(QGraphicsItem *parent = 0);int type() const override{return Type;}
private:QPolygonF m_boxItem;
};#endif // MYITEM_H

myitem.cpp

#include "myitem.h"
#include <QBrush>
myItem::myItem(QGraphicsItem *parent)
{m_boxItem << QPointF(0,0) << QPointF(30,0)<< QPointF(30,30) << QPointF(0,30)<< QPointF(0,0);setPolygon(m_boxItem);//颜色随机QColor color( (qrand() % 256),(qrand() % 256),(qrand() % 256) );QBrush brush(color);setBrush(brush);//可移动setFlag(QGraphicsItem::ItemIsMovable);//可选中setFlag(QGraphicsItem::ItemIsSelectable);
}

重写 QGraphicsScene(场景)

myscene.h

#ifndef MYSCENE_H
#define MYSCENE_H#include <QGraphicsScene>
#include <QObject>
#include "myitem.h"
class myScene : public QGraphicsScene
{Q_OBJECT
public:myScene(QObject *parent = 0);
signals:void itemMoveSignal(myItem* item,const QPointF position);protected:void mousePressEvent(QGraphicsSceneMouseEvent *event);void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);private:QGraphicsItem * m_Item;QPointF m_oldPos;
};#endif // MYSCENE_H

myscene.cpp

#include "myscene.h"
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
myScene::myScene(QObject *parent)
{m_Item = 0;}void myScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{QPointF mousePos (event->buttonDownScenePos(Qt::LeftButton).x(),event->buttonDownScenePos(Qt::LeftButton).y());const QList<QGraphicsItem* >itemList = items(mousePos);m_Item = itemList.isEmpty() ? 0 :itemList.first();if(m_Item != 0 && event->button() == Qt::LeftButton)m_oldPos = m_Item->pos();QGraphicsScene::mousePressEvent(event);}void myScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{if(m_Item != 0 && event->button() == Qt::LeftButton){if(m_oldPos != m_Item->pos())//发送位置移动的信号emit itemMoveSignal(qgraphicsitem_cast<myItem*>(m_Item),m_oldPos);m_Item = 0;}QGraphicsScene::mouseReleaseEvent(event);
}

下面重写的 QUndoCommand 才是实现撤回和回撤的模块

重写 QUndoCommand 就是重写父类的 undo() 和 redo() 方法

mycommand.h

#ifndef MYCOMMAND_H
#define MYCOMMAND_H#include <QUndoCommand>
#include "myitem.h"
#include "myscene.h"
//添加item
class addCommand :public QUndoCommand
{
public :addCommand(QGraphicsScene* graphicsScene,QUndoCommand* parent = 0);void redo() override;//重写这两个函数void undo() override;
private:myItem* m_item;QGraphicsScene* m_scene;QPointF m_initPos;
};
//移动item
class moveCommand:public QUndoCommand
{
public:moveCommand(myItem* item,const QPointF oldPos,QUndoCommand* parent = 0);void redo() override;//重写这两个函数void undo() override;
private:myItem* m_item;QPointF m_oldPos;QPointF m_newPos;};#endif // MYCOMMAND_H

mycommand.cpp

#include "mycommand.h"addCommand::addCommand(QGraphicsScene *graphicsScene, QUndoCommand *parent)
{m_scene = graphicsScene;m_item = new myItem();m_initPos = QPointF(10,10); //初始化item 生成的位置setText("add item");//undoView 中就会显示(父类的方法)
}void addCommand::redo()//stack push 时 会自动调用
{m_scene->addItem(m_item);m_item->setPos(m_initPos);m_scene->clearSelection();m_scene->update();
}void addCommand::undo()
{m_scene->removeItem(m_item);m_scene->update();
}moveCommand::moveCommand(myItem *item, const QPointF oldPos, QUndoCommand *parent)
{m_item = item;m_newPos = m_item->pos();m_oldPos = oldPos;
}void moveCommand::redo()
{m_item->setPos(m_newPos);setText(QString("Move Item:(%1,%2)").arg(m_item->pos().rx()).arg(m_item->pos().ry()));
}void moveCommand::undo()
{m_item->setPos(m_oldPos);m_item->scene()->update();setText(QString("Move Item:(%1,%2)").arg(m_item->pos().rx()).arg(m_item->pos().ry()));
}

主界面

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPushButton>
#include <QGraphicsView>
#include <QUndoStack>
#include <QUndoView>#include "myscene.h"
#include "myitem.h"
#include "mycommand.h"
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();void initUi();void initAction();void addItem();void itemMoved(myItem* item,QPointF pos);private:Ui::Widget *ui;QPushButton* m_addItemBtn;QAction* m_undoAction;QAction* m_redoAction;myScene *m_scene;QUndoStack* m_undoStack;QUndoView* m_undoView;
};#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QLayout>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);initAction();initUi();
}Widget::~Widget()
{delete ui;
}void Widget::initUi()
{this->setWindowTitle("码农小明--撤销回撤");m_addItemBtn = new QPushButton();m_addItemBtn->setText("add Item");connect(m_addItemBtn,&QPushButton::clicked,this,&Widget::addItem);m_scene = new myScene();QBrush brush(Qt::gray);m_scene->setSceneRect(QRect(0,0,200,300));m_scene->setBackgroundBrush(brush);connect(m_scene,&myScene::itemMoveSignal,this,&Widget::itemMoved);QGraphicsView *view = new QGraphicsView(m_scene);QVBoxLayout *pLayout = new QVBoxLayout();pLayout->addWidget(m_addItemBtn);pLayout->addWidget(view);m_undoView = new QUndoView(m_undoStack);//右面显示栈内容的view(不setText就是空的)QHBoxLayout *pHLayout = new QHBoxLayout();pHLayout->addLayout(pLayout);pHLayout->addWidget(m_undoView);this->setLayout(pHLayout);this->resize(500,400);}void Widget::initAction()
{m_undoStack = new QUndoStack(this);//存放操作的栈m_undoAction = m_undoStack->createUndoAction(this,"Undo");m_undoAction->setShortcut(QKeySequence::Undo);m_redoAction = m_undoStack->createRedoAction(this,"Redo");m_redoAction->setShortcut(QKeySequence::Redo);this->addAction(m_undoAction);this->addAction(m_redoAction);
}void Widget::addItem()
{QUndoCommand* add = new addCommand(m_scene);m_undoStack->push(add);//入栈操作 会自动调用 addCommand 的 redo}void Widget::itemMoved(myItem *item, QPointF pos)
{m_undoStack->push(new moveCommand(item,pos));//入栈操作
}
        98年菜鸡一枚,请大佬们多多关照!

Qt QUndoCommand(实现撤回和回撤)相关推荐

  1. Qt撤销回/撤框架:QUndoCommand

    一.描述 1.QUndoCommand表示对文档的单个编辑操作.例如,在文本编辑器中插入或删除文本块.QUndoCommand可以使用redo()将更改应用于文档,并使用undo()撤消更改.这些功能 ...

  2. 【翻译】Qt撤销/回撤框架概述

    一.简介 Qt的撤销/回撤框架是基于命令(Command)模式的实现,用于在应用程序中实现撤销/回撤功能. 命令模式基于这样一种思想:应用程序中的所有编辑都是通过创建命令对象的实例来完成的.命令对象将 ...

  3. git的历史版本拉分支、回撤revert、回退reset

    一.历史版本拉分支 假如我们要从3.0回退到1.0版本拉分支修改,那么在log找到1.0提交记录右键选择checkout,点击checkout之后当前工作区即回退到该提交的历史版本中. 然后,我们对1 ...

  4. Flink源码剖析:回撤流

    文章目录 1. 定义 2. 示例 2.1 源码分析 2.1.1 聚合算子回撤 2.1.2 Sink算子回撤 2.1.3 聚合算子回撤 VS Sink算子回撤 1. 定义 Flink中,Kafka So ...

  5. android环信3.0v回撤,环信Android消息回撤

    环信现在的消息回撤开发文档没有更新, 所以得自己去写, 本人贡献点小东西.本项目用的SDK版本为3.3.1. 1. 首先在聊天消息里添加消息长按事件监听,里面添加撤回消息选项. 撤回点击之后处理为: ...

  6. 股票python量化交易016-计算最大回撤

    什么是最大回撤? 资产分析中的最大回撤指的是在投资期间内可能出现最大损失的情况,即产品净值走到最低点时股票收益率撤回幅度的最大值,用来衡量账户的抗风险能力,是一个非常重要的风险指标! 如何计算最大回撤 ...

  7. flink回撤流分析

    Flink SQL 更新数据含有回撤数据的问题 案例问题一 问题描述 CREATE TABLE kafka_source (`policy_id` BIGINT ,`premium` int ,`gm ...

  8. 已经push到远端的代码 如何回撤? --转载

    已经push到远端的代码 如何回撤? 1.第一种情况:还没有push,只是在本地commit 2.push 代码已经更新到远程仓库 个人实操命名 工作遇到已经push到gitlab的代码,想撤回,在此 ...

  9. SVN 撤回(回滚)提交的代码

    转: SVN 撤回(回滚)提交的代码 2016年12月20日 17:20:58 怀色 阅读数 68614 标签: svn svn回滚 版本回滚 更多 个人分类: svn 版权声明:本文为博主原创文章, ...

最新文章

  1. python实现二叉树的重建1 之由前序遍历和中序遍历重建
  2. 打印HotSpot VM采用自动优化参数
  3. thinkphp php resque,麻花儿
  4. C#语言-07.文件操作
  5. Django--实现分页功能,并且基于cookie实现用户定制每页的数据条数
  6. linux获取主板温度电压_自学修电脑:常见主板报警声解析!
  7. php http头设置相关信息
  8. taskscheduler java_java – 针对不同任务的不同taskScheduler
  9. Windows 安装 MongoDB 和 可视化工具Robo3T
  10. 人机交互大作业_人机交互专业:多领域交叉的高能学科
  11. 宠物合成网站源码_为什么加工宠物食品做不到真正的“清洁”?
  12. 直播预告丨 统一数据操作平台— CloudQuery 应用指南
  13. centos7.2下查看的java版本号
  14. 关于计算机的知识古人,世界仅是一串二进制编码?我们是虚拟的?古人早就给出了答案...
  15. 机器学习基石笔记9——机器可以怎样学习(1)
  16. 有没有什么免费的网页视频录制软件?PC端视频录制软件集合
  17. better-scroll的使用以及常见的api总结
  18. 用户登录短信验证码的实现
  19. Ava 自动化测试----对函数的简单测试和对Http接口的测试
  20. 深拷贝工具类DeepCopyUtil

热门文章

  1. linux mount (挂载命令)详解
  2. 快速将纸质文件变为电子稿件
  3. python之路(二) 2019.2.28
  4. js轮播图片小圆点变化_JavaScript banner轮播 左右切换 圆点点击切换
  5. 【物联网】行排式二维条码 介绍
  6. ARM内核中寄存器的浅见
  7. linux grep命令
  8. 学校计算机教室墙面设计,学校微机室计算机互联网信息文化墙
  9. 曝移动版iPhone 5S 11月上市:售价5599元
  10. 0929误删除innodb ibdata数据文件