c++实现qtableview支持撤销回退CustomTableModel::onStackChanged
时间: 2024-01-07 21:05:00 浏览: 47
实现QTableView支持撤销回退需要以下步骤:
1. 创建一个自定义的数据模型 CustomTableModel,继承自 QAbstractTableModel,并添加一个 QUndoStack 对象用于记录撤销和回退操作。
2. 重写 CustomTableModel 的 setData() 函数,将修改操作封装成一个 QUndoCommand 对象并加入 QUndoStack 中。
3. 实现撤销和回退操作。可以通过调用 QUndoStack 的 undo() 和 redo() 方法来实现。同时,还需要根据当前的撤销和回退状态来更新 QTableView 的显示。
以下是示例代码:
```c++
#include <QUndoStack>
#include <QAbstractTableModel>
#include <QTableView>
class CustomTableModel : public QAbstractTableModel {
public:
CustomTableModel(QObject* parent = nullptr) : QAbstractTableModel(parent) {
m_undoStack = new QUndoStack(this);
}
bool setData(const QModelIndex& index, const QVariant& value, int role) override {
if (index.isValid() && role == Qt::EditRole) {
// 封装修改操作成 QUndoCommand 并加入 QUndoStack 中
QUndoCommand* editCommand = new EditCommand(this, index, value);
m_undoStack->push(editCommand);
return true;
}
return false;
}
int rowCount(const QModelIndex& parent = QModelIndex()) const override {
return m_data.size();
}
int columnCount(const QModelIndex& parent = QModelIndex()) const override {
return m_header.size();
}
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override {
if (index.isValid() && role == Qt::DisplayRole) {
return m_data.at(index.row()).at(index.column());
}
return QVariant();
}
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
return m_header.at(section);
}
return QVariant();
}
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override {
beginInsertRows(parent, row, row + count - 1);
for (int i = 0; i < count; ++i) {
m_data.insert(row, QVector<QString>(m_header.size()));
}
endInsertRows();
return true;
}
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override {
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; ++i) {
m_data.removeAt(row);
}
endRemoveRows();
return true;
}
void setHeader(const QStringList& header) {
m_header = header;
emit headerDataChanged(Qt::Horizontal, 0, m_header.size() - 1);
}
QUndoStack* undoStack() const {
return m_undoStack;
}
private:
class EditCommand : public QUndoCommand {
public:
EditCommand(CustomTableModel* model, const QModelIndex& index, const QVariant& value)
: m_model(model), m_index(index), m_newValue(value) {
m_oldValue = m_model->data(m_index, Qt::EditRole);
setText(QString("Edit %1").arg(m_oldValue.toString()));
}
void undo() override {
m_model->setData(m_index, m_oldValue, Qt::EditRole);
}
void redo() override {
m_model->setData(m_index, m_newValue, Qt::EditRole);
}
private:
CustomTableModel* m_model;
QModelIndex m_index;
QVariant m_oldValue;
QVariant m_newValue;
};
QVector<QVector<QString>> m_data;
QStringList m_header;
QUndoStack* m_undoStack;
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
// 创建数据模型和表格视图
CustomTableModel model;
QStringList header;
header << "Name" << "Age" << "Gender";
model.setHeader(header);
model.insertRows(0, 3);
QTableView view;
view.setModel(&model);
view.show();
// 创建撤销回退操作的动作
QAction* undoAction = model.undoStack()->createUndoAction(&view, "Undo");
QAction* redoAction = model.undoStack()->createRedoAction(&view, "Redo");
view.addAction(undoAction);
view.addAction(redoAction);
return app.exec();
}
```
在上面的示例中,CustomTableModel 类中添加了一个 QUndoStack 对象,并将修改操作封装成一个 EditCommand 对象,然后通过 QUndoStack 的 push() 方法将其加入栈中。在 setData() 函数中,我们只需要创建一个 EditCommand 对象并将其加入 QUndoStack 中即可。
在 main() 函数中,我们创建了一个 CustomTableModel 对象和一个 QTableView 对象,并将其设置为模型的显示视图。然后,我们使用 QUndoStack 的 createUndoAction() 和 createRedoAction() 方法创建了撤销和回退操作的动作,并将其添加到 QTableView 的操作菜单中。
当用户在表格视图中修改数据时,这些修改操作就会被记录到 QUndoStack 中。用户可以通过撤销和回退操作来撤销或者重做这些操作。同时,我们还可以根据当前的撤销和回退状态来更新 QTableView 的显示,使其始终反映当前的数据状态。