c++实现qtableview支持撤销回退功能
时间: 2024-02-01 17:16:31 浏览: 178
利用QTableView表格视图实现右击菜单删除功能.zip
要实现Qt的QTableView支持撤销回退功能,需要按以下步骤进行操作:
1. 创建一个记录表格数据的类,并在其中添加用于撤销和重做的操作。
```c++
class TableModel : public QAbstractTableModel
{
public:
TableModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool insertRows(int position, int rows, const QModelIndex &parent = QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()) override;
// 撤销重做相关操作
void undo();
void redo();
bool canUndo() const;
bool canRedo() const;
private:
QVector<QVector<QVariant>> m_data;
QVector<QVector<QVariant>> m_undoStack;
QVector<QVector<QVariant>> m_redoStack;
};
```
2. 在构造函数中初始化记录数据的变量,并将其与视图绑定。
```c++
TableModel::TableModel(QObject *parent)
: QAbstractTableModel(parent)
{
m_data.resize(10, QVector<QVariant>(10));
for (int row = 0; row < 10; ++row) {
for (int col = 0; col < 10; ++col) {
m_data[row][col] = QString("(%1,%2)").arg(row).arg(col);
}
}
}
```
3. 实现数据模型的基本功能,包括获取行数、列数、单元格数据、单元格编辑等。
```c++
int TableModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return m_data.size();
}
int TableModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return m_data[0].size();
}
QVariant TableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole) {
return m_data[index.row()][index.column()];
}
return QVariant();
}
bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
m_undoStack.push_back(m_data);
m_redoStack.clear();
m_data[index.row()][index.column()] = value;
emit dataChanged(index, index, {role});
return true;
}
return false;
}
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
bool TableModel::insertRows(int position, int rows, const QModelIndex &parent)
{
m_undoStack.push_back(m_data);
m_redoStack.clear();
beginInsertRows(parent, position, position + rows - 1);
for (int row = 0; row < rows; ++row) {
m_data.insert(position, QVector<QVariant>(m_data[0].size()));
}
endInsertRows();
return true;
}
bool TableModel::removeRows(int position, int rows, const QModelIndex &parent)
{
m_undoStack.push_back(m_data);
m_redoStack.clear();
beginRemoveRows(parent, position, position + rows - 1);
m_data.erase(m_data.begin() + position, m_data.begin() + position + rows);
endRemoveRows();
return true;
}
```
4. 实现撤销和重做操作。在撤销时,将当前数据保存到重做栈中,并从撤销栈中取出上一次的数据,更新视图显示。在重做时,将当前数据保存到撤销栈中,并从重做栈中取出下一次的数据,更新视图显示。
```c++
void TableModel::undo()
{
if (canUndo()) {
m_redoStack.push_back(m_data);
m_data = m_undoStack.back();
m_undoStack.pop_back();
emit dataChanged(index(0, 0), index(m_data.size() - 1, m_data[0].size() - 1), {});
}
}
void TableModel::redo()
{
if (canRedo()) {
m_undoStack.push_back(m_data);
m_data = m_redoStack.back();
m_redoStack.pop_back();
emit dataChanged(index(0, 0), index(m_data.size() - 1, m_data[0].size() - 1), {});
}
}
bool TableModel::canUndo() const
{
return !m_undoStack.empty();
}
bool TableModel::canRedo() const
{
return !m_redoStack.empty();
}
```
5. 在主窗口中创建QTableView,并将其与数据模型绑定。同时,创建撤销和重做的按钮,并在点击时调用数据模型的撤销和重做操作。
```c++
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QTableView *tableView = new QTableView(this);
TableModel *model = new TableModel(this);
tableView->setModel(model);
setCentralWidget(tableView);
QAction *undoAction = new QAction(tr("&Undo"), this);
undoAction->setShortcuts(QKeySequence::Undo);
connect(undoAction, &QAction::triggered, model, &TableModel::undo);
QAction *redoAction = new QAction(tr("&Redo"), this);
redoAction->setShortcuts(QKeySequence::Redo);
connect(redoAction, &QAction::triggered, model, &TableModel::redo);
QToolBar *toolBar = addToolBar(tr("Edit"));
toolBar->addAction(undoAction);
toolBar->addAction(redoAction);
}
```
这样,就可以在Qt的QTableView中实现撤销和重做的功能了。
阅读全文