一、描述
1、QUndoCommand表示对文档的单个编辑操作。例如,在文本编辑器中插入或删除文本块。QUndoCommand可以使用redo()将更改应用于文档,并使用undo()撤消更改。这些功能的实现必须在派生类中提供。如:
2、QUndoCommand对象由它们被压入的堆栈所拥有。如果命令已被撤消并且推送了新命令,则QUndoStack会删除该命令。例如:
MyCommand *command1 = new MyCommand();
stack->push(command1);
MyCommand *command2 = new MyCommand();
stack->push(command2);
stack->undo();
MyCommand *command3 = new MyCommand();
stack->push(command3); // command2被删除
3、当一个命令被push时,它将成为堆栈中最上面的命令。
4、为了支持命令压缩,QUndoCommand有一个id()和虚拟函数mergeWith()。这些函数由QUndoStack::push()使用。
5、为了支持命令宏,一个QUndoCommand对象可以有任意数量的子命令。撤消或重做父命令将导致撤消或重做子命令。可以在构造函数中将命令显式分配给父级。在这种情况下,命令将由父级拥有。
6、父级很多时候是一个空命令,空命令在于它不提供自己的undo()和redo()实现。相反,它使用这些函数的基本实现,只需对其所有子函数调用undo()或redo()。但是,父级应该有一个有意义的text()。
二、成员函数
1、QUndoCommand(const QString &text, QUndoCommand *parent = nullptr)
构造一个QUndoCommand对象。如果parent不是nullptr,则此命令将附加到parent的子列表中。然后,父命令拥有此命令,并将在其析构函数中将其删除。
2、QString actionText()
返回一个简短的文本字符串,描述此命令的作用; 例如“插入文本”。
3、const QUndoCommand *child(int index)
获取子命令。
4、[virtual] int id()
返回此命令的ID。命令ID用于命令压缩。如果命令不支持压缩,则必须为-1。如果命令支持压缩,则必须在派生类中重写此功能以返回正确的ID。QUndoStack::push()将仅尝试合并两个具有相同ID且ID不为-1的命令。
5、bool isObsolete()
返回命令是否过时。
6、[virtual] bool mergeWith(const QUndoCommand *command)
尝试将此命令与command合并。成功返回true,否则返回false。如果此函数返回true,则调用此命令的redo()必须与回撤此命令和命令具有相同的效果。同样,调用此命令的undo()必须与撤消命令和此命令具有相同的效果。如果两个命令具有相同的ID,并且ID不为-1,则QUndoStack仅尝试合并两个命令。默认实现返回false。
7、[virtual] void redo()
回撤。此函数必须在派生类中实现。默认实现是在所有子命令上调用redo()。
8、void setObsolete(bool obsolete)
设置命令是否过时。
9、void setText(const QString &text) / QString QUndoCommand::text() const
设置描述此命令作用的文本。
10、[virtual] void undo()
撤销。此函数必须在派生类中实现。默认实现是以相反的顺序在所有子命令上调用undo()。
三、一个使用示例:使用撤销/回撤框架添加和撤销添加按钮的例子
#include
#include
class AddBtnCommand : public QUndoCommand
{
public:
AddBtnCommand(QWidget *doc, QUndoCommand *parent = 0);
void undo() Q_DECL_OVERRIDE;
void redo() Q_DECL_OVERRIDE;
private:
QWidget * doc;
class QPushButton * btn{nullptr};
};
AddBtnCommand::AddBtnCommand(QWidget *doc, QUndoCommand *parent):
QUndoCommand(parent),
doc(doc)
{
}
void AddBtnCommand::undo()
{
if(btn)
{
btn->deleteLater();
btn = nullptr;
}
}
void AddBtnCommand::redo()
{
if(!btn)
{
btn = new QPushButton("新建按钮",doc);
btn->move(20,20);
btn->show();
}
}
继承QUndoCommand实现添加按钮的命令,undo()中删除按钮,redo()中再次添加按钮。
使用命令:
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
undoStack = new QUndoStack(this);
}
//添加命令
void Form::on_pushButton_clicked()
{
undoStack->push(new AddBtnCommand(this));
}
//撤销操作
void Form::on_pushButton_2_clicked()
{
undoStack->undo();
}
//回撤操作
void Form::on_pushButton_3_clicked()
{
undoStack->redo();
}
把命令添加到QUndoStack中后会执行一次命令的redo()。
效果: