如何处理:qsqltablemodel 不加载视图
How to deal: qsqltablemodel does not load view
我有一个非常简单的系统,在 SQLite 数据库中有 2 个视图,在桌面 Qt 小部件应用程序中有 2 个 table 视图:
- 第一个视图是 'seller_view',它只是通过 QSqlTableModel 在 App 的 tableView 中正确打印。
- 第二个是 'customer_view'(设置与上面相同),它不打印任何数据,但显示模型的 headers,这是在构造函数中设置的。
所以,我们遇到了一个奇怪的情况:
SQL 在SQLiteStudio中查看数据(查看'customer_view')
模型设置
// model for tableView
model = new QSqlTableModel();
model->setTable("customer_view");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
updateView();
model->setHeaderData(0, Qt::Horizontal, tr("ID"));
model->setHeaderData(1, Qt::Horizontal, tr("Ім'я")); // only organizations will have ipn
model->setHeaderData(2, Qt::Horizontal, tr("К-сть авто"));
model->setHeaderData(3, Qt::Horizontal, tr("Адреса"));
model->setHeaderData(4, Qt::Horizontal, tr("Номер"));
model->setHeaderData(5, Qt::Horizontal, tr("Ел.пошта"));
model->setHeaderData(6, Qt::Horizontal, tr("ІБАН"));
model->setHeaderData(7, Qt::Horizontal, tr("Банк"));
model->setHeaderData(8, Qt::Horizontal, tr("ЄДРПОУ"));
model->setHeaderData(9, Qt::Horizontal, tr("ІПН"));
ui->tableView->setModel(model);
ui->tableView->setColumnHidden(ID_COLUMN_INDEX, true); // hide ID
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
connect(model, &QSqlTableModel::dataChanged, this, &Customers::handleDataChange);
应用程序中的 QTableView 'customer_view'
我有一些结论:
- QSqlTableModel 工作正常,因为 tables(views) 名称(我检查了 10 次)是正确的,并且它正确显示列名称,所以我可以说,tableView 模型设置没问题。
- SQL 视图是正确的,因为 SQLiteStudio 显示了它应该显示的数据。同样,视图名称是正确的
- 如果我将工作模型的 QSqlTableModel::setTable('seller_view') 替换为 'customer_view',它不会像预期的那样显示数据。所以,我几乎可以肯定问题出在 SQL 数据库中。
P.S.: 我还尝试更改视图名称 'customer_view' -> 'cus'。没有任何变化
P.S.S.: 我以正确的方式设置了数据库,因为在 SQLiteStudio 中更改 'seller' 数据会导致在 App 中更改 'seller_view'。所以,'customer_view' 的问题是 100%,我很困惑。也许查询破坏了我的数据库?
SELECT customer.id,
customer.name,
COUNT(car.id),
customer.address,
customer.number,
customer.email,
customer.iban,
customer.bank,
customer.edrpoy,
customer.ipn
FROM customer
LEFT JOIN
car ON customer.id = car.customer_id
GROUP BY customer.id
P.S.S.S:
void Customers::updateView()
{
model->select();
}
seller_view sql
SELECT seller.id,
seller.name,
seller.address,
seller.number,
seller.iban,
seller.bank,
seller.edrpoy,
seller.ipn
FROM seller
P.S.S.S.S(这些东西的一切都正常工作并更新 table 和 SQLiteStudio 中的视图,但模型未显示为 seller_view ):
void Customers::on_btn_add_clicked()
{
QSqlQuery qry;
qry.exec("INSERT INTO customer(name) VALUES(NULL)");
updateView();
}
void Customers::on_btn_del_clicked()
{
const auto selected_indexes = ui->tableView->selectionModel()->selectedIndexes();
QSqlQuery qry;
if (!selected_indexes.isEmpty())
{
qry.exec("PRAGMA foreign_keys=ON");
qry.exec("DELETE FROM customer WHERE id=" + selected_indexes.at(0).siblingAtColumn(ID_COLUMN_INDEX)
.data(Qt::DisplayRole).toString()
);
}
updateView();
}
void Customers::handleDataChange(const QModelIndex &topLeft, const QModelIndex &)
{
const QVector<int> notEditableColumns = {
2 /* Cars count is NOT EDITABLE */
};
const int column = topLeft.column();
const QString data = topLeft.data(Qt::DisplayRole).toString();
const QString customer_id = topLeft.siblingAtColumn(ID_COLUMN_INDEX).data(Qt::DisplayRole).toString();
if (!notEditableColumns.contains(column)) {
switch (column) {
case 1: {
handleSimpleCellChange("name", data, customer_id);
} break;
case 3: {
handleSimpleCellChange("address", data, customer_id);
} break;
case 4: {
handleSimpleCellChange("number", data, customer_id);
} break;
case 5: {
handleSimpleCellChange("email", data, customer_id);
} break;
case 6: {
handleSimpleCellChange("iban", data, customer_id);
} break;
case 7: {
handleSimpleCellChange("bank", data, customer_id);
} break;
case 8: {
handleSimpleCellChange("edrpoy", data, customer_id);
} break;
case 9: {
handleSimpleCellChange("ipn", data, customer_id);
} break;
}
}
updateView();
}
void Customers::handleSimpleCellChange(const QString &columnName, const QString &data, const QString &customer_id)
{
QSqlQuery qry;
const QString query_str = "UPDATE customer SET %1=%2 WHERE id=%3";
qry.exec(query_str.arg(columnName, data, customer_id));
}
由于您没有使用模型直接写入基础表,我会尝试 QSqlQueryModel
:只需使用它而不是 QSqlTableModel
,并替换您的
model->select();
与
model.setQuery("select * from customer_view");
由于此模型是只读的,您可能希望完全放弃 model/view 策略,并回退到使用 QSqlQuery 并用其结果填充 QTableWidget。此方法应该比使用提供 data/setData 实现的子类模型更快,同时考虑到您已经编写了代码以在单个单元格数据更改的基础上编辑数据库。
我有一个非常简单的系统,在 SQLite 数据库中有 2 个视图,在桌面 Qt 小部件应用程序中有 2 个 table 视图:
- 第一个视图是 'seller_view',它只是通过 QSqlTableModel 在 App 的 tableView 中正确打印。
- 第二个是 'customer_view'(设置与上面相同),它不打印任何数据,但显示模型的 headers,这是在构造函数中设置的。
所以,我们遇到了一个奇怪的情况:
SQL 在SQLiteStudio中查看数据(查看'customer_view')
模型设置
// model for tableView
model = new QSqlTableModel();
model->setTable("customer_view");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
updateView();
model->setHeaderData(0, Qt::Horizontal, tr("ID"));
model->setHeaderData(1, Qt::Horizontal, tr("Ім'я")); // only organizations will have ipn
model->setHeaderData(2, Qt::Horizontal, tr("К-сть авто"));
model->setHeaderData(3, Qt::Horizontal, tr("Адреса"));
model->setHeaderData(4, Qt::Horizontal, tr("Номер"));
model->setHeaderData(5, Qt::Horizontal, tr("Ел.пошта"));
model->setHeaderData(6, Qt::Horizontal, tr("ІБАН"));
model->setHeaderData(7, Qt::Horizontal, tr("Банк"));
model->setHeaderData(8, Qt::Horizontal, tr("ЄДРПОУ"));
model->setHeaderData(9, Qt::Horizontal, tr("ІПН"));
ui->tableView->setModel(model);
ui->tableView->setColumnHidden(ID_COLUMN_INDEX, true); // hide ID
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
connect(model, &QSqlTableModel::dataChanged, this, &Customers::handleDataChange);
应用程序中的 QTableView 'customer_view'
我有一些结论:
- QSqlTableModel 工作正常,因为 tables(views) 名称(我检查了 10 次)是正确的,并且它正确显示列名称,所以我可以说,tableView 模型设置没问题。
- SQL 视图是正确的,因为 SQLiteStudio 显示了它应该显示的数据。同样,视图名称是正确的
- 如果我将工作模型的 QSqlTableModel::setTable('seller_view') 替换为 'customer_view',它不会像预期的那样显示数据。所以,我几乎可以肯定问题出在 SQL 数据库中。
P.S.: 我还尝试更改视图名称 'customer_view' -> 'cus'。没有任何变化
P.S.S.: 我以正确的方式设置了数据库,因为在 SQLiteStudio 中更改 'seller' 数据会导致在 App 中更改 'seller_view'。所以,'customer_view' 的问题是 100%,我很困惑。也许查询破坏了我的数据库?
SELECT customer.id,
customer.name,
COUNT(car.id),
customer.address,
customer.number,
customer.email,
customer.iban,
customer.bank,
customer.edrpoy,
customer.ipn
FROM customer
LEFT JOIN
car ON customer.id = car.customer_id
GROUP BY customer.id
P.S.S.S:
void Customers::updateView()
{
model->select();
}
seller_view sql
SELECT seller.id,
seller.name,
seller.address,
seller.number,
seller.iban,
seller.bank,
seller.edrpoy,
seller.ipn
FROM seller
P.S.S.S.S(这些东西的一切都正常工作并更新 table 和 SQLiteStudio 中的视图,但模型未显示为 seller_view ):
void Customers::on_btn_add_clicked()
{
QSqlQuery qry;
qry.exec("INSERT INTO customer(name) VALUES(NULL)");
updateView();
}
void Customers::on_btn_del_clicked()
{
const auto selected_indexes = ui->tableView->selectionModel()->selectedIndexes();
QSqlQuery qry;
if (!selected_indexes.isEmpty())
{
qry.exec("PRAGMA foreign_keys=ON");
qry.exec("DELETE FROM customer WHERE id=" + selected_indexes.at(0).siblingAtColumn(ID_COLUMN_INDEX)
.data(Qt::DisplayRole).toString()
);
}
updateView();
}
void Customers::handleDataChange(const QModelIndex &topLeft, const QModelIndex &)
{
const QVector<int> notEditableColumns = {
2 /* Cars count is NOT EDITABLE */
};
const int column = topLeft.column();
const QString data = topLeft.data(Qt::DisplayRole).toString();
const QString customer_id = topLeft.siblingAtColumn(ID_COLUMN_INDEX).data(Qt::DisplayRole).toString();
if (!notEditableColumns.contains(column)) {
switch (column) {
case 1: {
handleSimpleCellChange("name", data, customer_id);
} break;
case 3: {
handleSimpleCellChange("address", data, customer_id);
} break;
case 4: {
handleSimpleCellChange("number", data, customer_id);
} break;
case 5: {
handleSimpleCellChange("email", data, customer_id);
} break;
case 6: {
handleSimpleCellChange("iban", data, customer_id);
} break;
case 7: {
handleSimpleCellChange("bank", data, customer_id);
} break;
case 8: {
handleSimpleCellChange("edrpoy", data, customer_id);
} break;
case 9: {
handleSimpleCellChange("ipn", data, customer_id);
} break;
}
}
updateView();
}
void Customers::handleSimpleCellChange(const QString &columnName, const QString &data, const QString &customer_id)
{
QSqlQuery qry;
const QString query_str = "UPDATE customer SET %1=%2 WHERE id=%3";
qry.exec(query_str.arg(columnName, data, customer_id));
}
由于您没有使用模型直接写入基础表,我会尝试 QSqlQueryModel
:只需使用它而不是 QSqlTableModel
,并替换您的
model->select();
与
model.setQuery("select * from customer_view");
由于此模型是只读的,您可能希望完全放弃 model/view 策略,并回退到使用 QSqlQuery 并用其结果填充 QTableWidget。此方法应该比使用提供 data/setData 实现的子类模型更快,同时考虑到您已经编写了代码以在单个单元格数据更改的基础上编辑数据库。