Qt QUndoStack、QUndoCommand(实现撤回和回撤)

admin 2022年9月19日00:41:34安全开发评论4 views5501字阅读18分20秒阅读模式

用到的类:

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)写的:
Qt QUndoStack、QUndoCommand(实现撤回和回撤)
 Qt QUndoStack、QUndoCommand(实现撤回和回撤)

重写 QGraphicsPolygonItem (方块)

myitem.h
#ifndef MYITEM_H#define MYITEM_H
#include
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 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 #include #include "myitem.h"class myScene : public QGraphicsScene{ Q_OBJECTpublic: 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 #include 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 QListitemList = 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(m_Item),m_oldPos); m_Item = 0; } QGraphicsScene::mouseReleaseEvent(event);}

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

重写 QUndoCommand 就是重写父类的 undo() 和 redo() 方法
mycommand.h
#ifndef MYCOMMAND_H#define MYCOMMAND_H
#include #include "myitem.h"#include "myscene.h"//添加itemclass 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;};//移动itemclass 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 #include #include #include #include
#include "myscene.h"#include "myitem.h"#include "mycommand.h"namespace Ui {class Widget;}
class Widget : public QWidget{ Q_OBJECT
public: 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 
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));//入栈操作}


摘自https://www.cnblogs.com/ybqjymy/p/12836278.html

原文始发于微信公众号(汇编语言):Qt QUndoStack、QUndoCommand(实现撤回和回撤)

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月19日00:41:34
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  Qt QUndoStack、QUndoCommand(实现撤回和回撤) http://cn-sec.com/archives/1302934.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: