Qt中的撤销/重做功能
作为一个例子,本例只实现了在列表控件“添加项”和“修改项名称”的2个操作。界面上显示一个列表框,列表框需要在界面设计器中设为IconMode,这样就会是图标在上文本在下的显示样式。“添加”按钮用来在列表框中加一个项。点击图标下面的文本可以修改文本名称。程序测试环境是VS2017和Qt5.9,测试结果功能正常,运行效果如下:
头文件:
class QListWidget; class MAddImage : public QUndoCommand { public: MAddImage(const QString &text, QListWidget* isrc, QUndoCommand *parent = Q_NULLPTR); ~MAddImage() override = default; void setActionInfo(const QPixmap& image, int where); void undo() override; void redo() override; private: QListWidget* src; QPixmap pixmap; int pos; }; class MChangeName : public QUndoCommand { public: MChangeName(const QString &text, QListWidget* isrc, QUndoCommand *parent = Q_NULLPTR); ~MChangeName() override = default; void setActionInfo(const QString& oldName, const QString& newName, int where); void undo() override; void redo() override; private: QListWidget* src; QString newText; QString oldText; int pos; };
CPP文件:
MAddImage::MAddImage(const QString &text, QListWidget* isrc, QUndoCommand *parent) : QUndoCommand(text, parent) { src = isrc; } void MAddImage::setActionInfo(const QPixmap& image, int where) { pixmap = image; pos = where; } void MAddImage::undo() { delete src->takeItem(pos); } void MAddImage::redo() { QListWidgetItem* item = new QListWidgetItem(QIcon(pixmap), QString(u8"未命名")); item->setFlags(Qt::ItemIsEditable | item->flags()); src->insertItem(pos, item); } MChangeName::MChangeName(const QString &text, QListWidget* isrc, QUndoCommand *parent) : QUndoCommand(text, parent) { src = isrc; } void MChangeName::setActionInfo(const QString& oldName, const QString& newName, int where) { oldText = oldName; newText = newName; pos = where; } void MChangeName::undo() { src->blockSignals(true); QListWidgetItem* item = src->item(pos); item->setText(oldText); src->blockSignals(false); } void MChangeName::redo() { src->blockSignals(true); QListWidgetItem* item = src->item(pos); item->setText(newText); src->blockSignals(false); }
在主窗口类中有几个槽函数需要实现以响应用户的操作。下面的代码中QtTest是主窗口类;ui.lwList是列表控件;(ui.)pbAdd是“添加”按钮;(ui.)pbUndo是“撤销”按钮;(ui.)pbRedo是“重做”按钮。operas是QtTest类成员变量,定义是 QUndoStack operas; ,它是Qt封装好的用于管理撤销/重做命令的类,详情可以查阅Qt帮助文档。
void QtTest::on_lwList_currentRowChanged(int row) { QListWidgetItem* it = ui.lwList->item(row); currEditText = it->text(); } void QtTest::on_lwList_itemChanged(QListWidgetItem *item) { MChangeName* changeAct = new MChangeName(u8"修改名称", ui.lwList); changeAct->setActionInfo(currEditText, item->text(), ui.lwList->row(item)); operas.push(changeAct); /* 由于push(...)自动触发redo()操作,因此这里重命名两次 */ } void QtTest::on_pbAdd_clicked() { QPixmap pixmap(100, 80); pixmap.fill(QColor(qrand() % 255, qrand() % 255, qrand() % 255)); MAddImage* addAct = new MAddImage(u8"添加图片", ui.lwList); addAct->setActionInfo(pixmap, ui.lwList->count()); operas.push(addAct); } void QtTest::on_pbUndo_clicked() { operas.undo(); } void QtTest::on_pbRedo_clicked() { operas.redo(); }