缓存 SQL 表
“缓存表”示例演示了如何使用表视图访问数据库,并将数据中的任何更改缓存起来,直到用户通过按钮显式提交这些更改为止。

该示例由一个类TableEditor 组成,这是一个自定义对话框控件,允许用户修改存储在数据库中的数据。我们将首先回顾该类的定义及其使用方法,然后详细探讨其实现细节。
TableEditor 类定义
TableEditor 类继承自 `QWidget `,这使得该表格编辑器控件成为一个顶级对话框窗口。
class TableEditor : public QWidget
{
Q_OBJECT
public:
explicit TableEditor(const QString &tableName, QWidget *parent = nullptr);
private slots:
void submit();
private:
QPushButton *submitButton;
QPushButton *revertButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QSqlTableModel *model;
};TableEditor 的构造函数接受两个参数:第一个是TableEditor 对象将操作的数据库表的引用;另一个是父控件的指针,该指针将传递给基类的构造函数。
请注意QSqlTableModel 变量的声明:正如本示例中将看到的,QSqlTableModel 类可用于向QTableView 等视图类提供数据。QSqlTableModel 类提供了一个可编辑的数据模型,使得从单个表中读取和写入数据库记录成为可能。它基于底层的QSqlQuery 类构建,后者提供了执行和操作SQL语句的手段。
我们还将演示如何利用表视图将数据变更缓存起来,直到用户明确要求提交这些变更为止。为此,除了模型和编辑器的按钮之外,我们还需要声明一个submit() 槽。
| 连接数据库 |
|---|
在使用 `TableEditor ` 类之前,我们必须先建立与包含待编辑表的数据库的连接:
|
TableEditor 类的实现
该类的实现仅包含两个函数:构造函数和submit() 槽。在构造函数中,我们创建并自定义数据模型以及各种窗口元素:
TableEditor::TableEditor(const QString &tableName, QWidget *parent)
: QWidget(parent)
{
model = new QSqlTableModel(this);
model->setTable(tableName);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("ID"));
model->setHeaderData(1, Qt::Horizontal, tr("First name"));
model->setHeaderData(2, Qt::Horizontal, tr("Last name"));首先,我们创建数据模型,并设置该模型将操作的目标 SQL 数据库表。 请注意,QSqlTableModel::setTable() 函数不会从表中查询数据,它仅获取字段信息。因此,我们稍后会调用QSqlTableModel::select() 函数,将表中的数据填充到模型中。可以通过指定过滤器和排序条件来自定义查询(更多详情请参阅QSqlTableModel 类的文档)。
我们还设置了模型的编辑策略。编辑策略决定了用户在视图中进行的更改何时才会实际应用到数据库中。由于我们希望将表视图(即模型)中的更改缓存起来,直到用户显式提交为止,因此我们选择了 `QSqlTableModel::OnManualSubmit ` 策略。其他可选策略包括 `QSqlTableModel::OnFieldChange ` 和 `QSqlTableModel::OnRowChange`。
最后,我们使用模型从 `QSqlQueryModel ` 类继承的 `setHeaderData()` 函数,设置视图标题中显示的标签。
QTableView *view = new QTableView;
view->setModel(model);
view->resizeColumnsToContents();然后,我们创建一个表格视图。QTableView 类提供了一个表格视图的默认模型/视图实现,即它实现了一个用于显示模型中项的表格视图。它还允许用户编辑这些项,并将更改存储在模型中。若要创建只读视图,请通过视图从QAbstractItemView 类继承的editTriggers 属性设置相应的标志。
为了让视图呈现我们的数据,我们使用setModel()函数将模型传递给视图。
submitButton = new QPushButton(tr("Submit"));
submitButton->setDefault(true);
revertButton = new QPushButton(tr("&Revert"));
quitButton = new QPushButton(tr("Quit"));
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(submitButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(revertButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);TableEditor 中的按钮是普通的QPushButton 对象。我们将它们添加到按钮框中,以确保按钮以符合当前控件样式的布局呈现。这样做的理由是,对话框和消息框通常会按照该平台的界面指南来安排按钮布局。 不同平台的对话框布局必然各不相同。`QDialogButtonBox `允许开发者向其中添加按钮,并会自动采用适合用户桌面环境的布局。
对话框中的大多数按钮都遵循特定的角色。当使用addButton() 函数将按钮添加到按钮框时,必须使用QDialogButtonBox::ButtonRole 枚举来指定该按钮的角色。此外,QDialogButtonBox 还提供了若干标准按钮(例如OK 、Cancel 、Save ),供您使用。这些按钮以标志形式存在,因此您可以在构造函数中将它们进行按位或(OR)运算组合。
connect(submitButton, &QPushButton::clicked, this, &TableEditor::submit);
connect(revertButton, &QPushButton::clicked, model, &QSqlTableModel::revertAll);
connect(quitButton, &QPushButton::clicked, this, &TableEditor::close);我们将Quit 按钮连接到表格编辑器的close()槽,并将Submit 按钮连接到我们的私有submit() 槽。后者将负责处理数据事务。最后,我们将Revert 按钮连接到模型的revertAll()槽,以撤销所有待处理的更改(即恢复原始数据)。
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(view);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Cached Table"));
}最后,我们将按钮框和表格视图添加到布局中,将该布局安装到表格编辑器控件上,并设置编辑器的窗口标题。
void TableEditor::submit()
{
model->database().transaction();
if (model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
QMessageBox::warning(this, tr("Cached Table"),
tr("The database reported an error: %1")
.arg(model->lastError().text()));
}
}每当用户点击“Submit ”按钮保存更改时,都会调用submit() 槽方法。
首先,我们使用QSqlDatabase::transaction()函数在数据库上启动一个事务。数据库事务是与数据库管理系统或类似系统交互的一个单元,其处理方式具有一致性和可靠性,并独立于其他事务。可通过QSqlTableModel::database()函数获取所用数据库的指针。
然后,我们尝试提交所有待处理的更改,即模型中已修改的项目。如果未发生错误,则使用QSqlDatabase::commit()函数将事务提交到数据库(请注意,在某些数据库中,如果数据库上存在一个活跃的QSqlQuery ,此函数将无法正常工作)。 否则,我们将使用QSqlDatabase::rollback()函数回滚事务,并向用户发出警告。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.