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)写的:

myitem.h
1 #ifndef MYITEM_H2 #define MYITEM_H3 4 #include5 6 class myItem :public QGraphicsPolygonItem7 {8 9 public: 10 11 enum {Type = UserType +1}; 12 13 explicit myItem(QGraphicsItem *parent = 0); 14 15 int type() const override{return Type;} 16 private: 17 QPolygonF m_boxItem; 18 }; 19 20 #endif // MYITEM_H
myitem.cpp
1 #include "myitem.h"2 #include3 myItem::myItem(QGraphicsItem *parent)4 {5 6 m_boxItem << QPointF(0,0) << QPointF(30,0)7 << QPointF(30,30) << QPointF(0,30)8 << QPointF(0,0);9 setPolygon(m_boxItem); 10 //颜色随机 11 QColor color( (qrand() % 256),(qrand() % 256),(qrand() % 256) ); 12 13 QBrush brush(color); 14 setBrush(brush); 15 //可移动 16 setFlag(QGraphicsItem::ItemIsMovable); 17 //可选中 18 setFlag(QGraphicsItem::ItemIsSelectable); 19 }
myscene.h
1 #ifndef MYSCENE_H2 #define MYSCENE_H3 4 #include5 #include 6 #include "myitem.h"7 class myScene : public QGraphicsScene8 {9 Q_OBJECT 10 public: 11 myScene(QObject *parent = 0); 12 signals: 13 14 void itemMoveSignal(myItem* item,const QPointF position); 15 16 protected: 17 void mousePressEvent(QGraphicsSceneMouseEvent *event); 18 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 19 20 private: 21 22 QGraphicsItem * m_Item; 23 QPointF m_oldPos; 24 }; 25 26 #endif // MYSCENE_H
myscene.cpp
1 #include "myscene.h"2 #include3 #include 4 myScene::myScene(QObject *parent)5 {6 m_Item = 0;7 8 }9 10 void myScene::mousePressEvent(QGraphicsSceneMouseEvent *event) 11 { 12 QPointF mousePos (event->buttonDownScenePos(Qt::LeftButton).x(), 13 event->buttonDownScenePos(Qt::LeftButton).y()); 14 const QList itemList = items(mousePos); 15 16 m_Item = itemList.isEmpty() ? 0 :itemList.first(); 17 18 if(m_Item != 0 && event->button() == Qt::LeftButton) 19 m_oldPos = m_Item->pos(); 20 21 QGraphicsScene::mousePressEvent(event); 22 23 } 24 25 void myScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 26 { 27 if(m_Item != 0 && event->button() == Qt::LeftButton) 28 { 29 if(m_oldPos != m_Item->pos()) 30 //发送位置移动的信号 31 emit itemMoveSignal(qgraphicsitem_cast (m_Item),m_oldPos); 32 m_Item = 0; 33 } 34 QGraphicsScene::mouseReleaseEvent(event); 35 }
重写 QUndoCommand 就是重写父类的 undo() 和 redo() 方法
mycommand.h
1 #ifndef MYCOMMAND_H2 #define MYCOMMAND_H3 4 #include5 #include "myitem.h"6 #include "myscene.h"7 //添加item8 class addCommand :public QUndoCommand9 { 10 public : 11 addCommand(QGraphicsScene* graphicsScene,QUndoCommand* parent = 0); 12 13 void redo() override;//重写这两个函数 14 void undo() override; 15 private: 16 17 myItem* m_item; 18 19 QGraphicsScene* m_scene; 20 21 QPointF m_initPos; 22 }; 23 //移动item 24 class moveCommand:public QUndoCommand 25 { 26 public: 27 moveCommand(myItem* item,const QPointF oldPos,QUndoCommand* parent = 0); 28 29 void redo() override;//重写这两个函数 30 void undo() override; 31 private: 32 myItem* m_item; 33 QPointF m_oldPos; 34 QPointF m_newPos; 35 36 }; 37 38 #endif // MYCOMMAND_H
mycommand.cpp
1 #include "mycommand.h"2 3 4 addCommand::addCommand(QGraphicsScene *graphicsScene, QUndoCommand *parent)5 {6 m_scene = graphicsScene;7 8 m_item = new myItem();9
10 m_initPos = QPointF(10,10); //初始化item 生成的位置
11
12 setText("add item");//undoView 中就会显示(父类的方法)
13 }
14
15 void addCommand::redo()//stack push 时 会自动调用
16 {
17 m_scene->addItem(m_item);
18 m_item->setPos(m_initPos);
19 m_scene->clearSelection();
20 m_scene->update();
21 }
22
23 void addCommand::undo()
24 {
25 m_scene->removeItem(m_item);
26 m_scene->update();
27 }
28
29 moveCommand::moveCommand(myItem *item, const QPointF oldPos, QUndoCommand *parent)
30 {
31 m_item = item;
32
33 m_newPos = m_item->pos();
34
35 m_oldPos = oldPos;
36 }
37
38 void moveCommand::redo()
39 {
40 m_item->setPos(m_newPos);
41 setText(QString("Move Item:(%1,%2)").arg(m_item->pos().rx()).arg(m_item->pos().ry()));
42 }
43
44 void moveCommand::undo()
45 {
46 m_item->setPos(m_oldPos);
47 m_item->scene()->update();
48 setText(QString("Move Item:(%1,%2)").arg(m_item->pos().rx()).arg(m_item->pos().ry()));
49 } widget.h
1 #ifndef WIDGET_H2 #define WIDGET_H3 4 #include5 #include 6 #include 7 #include 8 #include 9 10 #include "myscene.h" 11 #include "myitem.h" 12 #include "mycommand.h" 13 namespace Ui { 14 class Widget; 15 } 16 17 class Widget : public QWidget 18 { 19 Q_OBJECT 20 21 public: 22 explicit Widget(QWidget *parent = 0); 23 ~Widget(); 24 25 void initUi(); 26 27 void initAction(); 28 29 void addItem(); 30 31 void itemMoved(myItem* item,QPointF pos); 32 33 private: 34 Ui::Widget *ui; 35 QPushButton* m_addItemBtn; 36 QAction* m_undoAction; 37 QAction* m_redoAction; 38 myScene *m_scene; 39 40 QUndoStack* m_undoStack; 41 QUndoView* m_undoView; 42 }; 43 44 #endif // WIDGET_H
widget.cpp
1 #include "widget.h"2 #include "ui_widget.h"3 #include4 5 Widget::Widget(QWidget *parent) :6 QWidget(parent),7 ui(new Ui::Widget)8 {9 ui->setupUi(this); 10 11 12 initAction(); 13 14 initUi(); 15 } 16 17 Widget::~Widget() 18 { 19 delete ui; 20 } 21 22 void Widget::initUi() 23 { 24 this->setWindowTitle("码农小明--撤销回撤"); 25 26 m_addItemBtn = new QPushButton(); 27 m_addItemBtn->setText("add Item"); 28 29 connect(m_addItemBtn,&QPushButton::clicked,this,&Widget::addItem); 30 31 m_scene = new myScene(); 32 QBrush brush(Qt::gray); 33 m_scene->setSceneRect(QRect(0,0,200,300)); 34 m_scene->setBackgroundBrush(brush); 35 36 connect(m_scene,&myScene::itemMoveSignal,this,&Widget::itemMoved); 37 38 39 QGraphicsView *view = new QGraphicsView(m_scene); 40 41 QVBoxLayout *pLayout = new QVBoxLayout(); 42 pLayout->addWidget(m_addItemBtn); 43 pLayout->addWidget(view); 44 45 46 m_undoView = new QUndoView(m_undoStack);//右面显示栈内容的view(不setText就是空的) 47 QHBoxLayout *pHLayout = new QHBoxLayout(); 48 pHLayout->addLayout(pLayout); 49 pHLayout->addWidget(m_undoView); 50 51 52 this->setLayout(pHLayout); 53 54 this->resize(500,400); 55 56 } 57 58 void Widget::initAction() 59 { 60 m_undoStack = new QUndoStack(this);//存放操作的栈 61 62 m_undoAction = m_undoStack->createUndoAction(this,"Undo"); 63 m_undoAction->setShortcut(QKeySequence::Undo); 64 65 m_redoAction = m_undoStack->createRedoAction(this,"Redo"); 66 m_redoAction->setShortcut(QKeySequence::Redo); 67 68 this->addAction(m_undoAction); 69 this->addAction(m_redoAction); 70 } 71 72 void Widget::addItem() 73 { 74 QUndoCommand* add = new addCommand(m_scene); 75 m_undoStack->push(add);//入栈操作 会自动调用 addCommand 的 redo 76 77 } 78 79 void Widget::itemMoved(myItem *item, QPointF pos) 80 { 81 m_undoStack->push(new moveCommand(item,pos));//入栈操作 82 }
上一篇:疑问的近义词是什么
下一篇:男人不能相信的10句话