You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Qt5+SQLite3中同时访问同一数据库的不同表

嘿,我来帮你搞定这个Qt5+SQLite3跨表展示日志的需求!要在列表视图里同时展示两张表的关联信息,核心是用SQL关联查询+Qt的数据库模型来实现,下面是具体的步骤和代码示例:

实现跨表日志展示方案

1. 先写关联两张表的SQL查询语句

log表只存了书籍的UID,要拿到对应的书名、作者,就得和allBooks表做关联查询。用INNER JOIN就能把两张表通过UID字段绑定起来,SQL语句如下:

SELECT 
    log.STUDENT,
    allBooks.NAME AS BOOK_NAME,
    allBooks.AUTHOR,
    log.ISSUED,
    log.RETURNED
FROM log
INNER JOIN allBooks ON log.UID = allBooks.UID;

如果担心有些日志记录对应的书籍已经被删除(allBooks里没有对应UID),可以把INNER JOIN换成LEFT JOIN,这样即使书籍信息不存在,日志记录依然会被保留,只是书籍相关字段会显示NULL。

2. 在日志对话框构造函数里实现模型与视图绑定

假设你的对话框类叫LogDialog,可以用QSqlQueryModel来承载自定义查询的结果,再绑定到视图上。这里建议用QTableView(比QListView更适合展示多列的日志数据),如果一定要用ListView,后面也会给你补充优化方案:

#include <QSqlQueryModel>
#include <QTableView>
#include <QVBoxLayout>
#include <QSqlDatabase>
#include <QDebug>

LogDialog::LogDialog(QWidget *parent) : QDialog(parent)
{
    // 先确保数据库连接已经初始化并打开(这里假设你已经在全局建立了名为"bookDB"的连接)
    QSqlDatabase db = QSqlDatabase::database("bookDB");
    if (!db.isOpen()) {
        qDebug() << "数据库连接失败:" << db.lastError().text();
        return;
    }

    // 创建查询模型,执行关联查询
    QSqlQueryModel *logModel = new QSqlQueryModel(this);
    logModel->setQuery(R"(
        SELECT 
            log.STUDENT,
            allBooks.NAME AS BOOK_NAME,
            allBooks.AUTHOR,
            log.ISSUED,
            log.RETURNED
        FROM log
        INNER JOIN allBooks ON log.UID = allBooks.UID
    )", db);

    // 设置表头的友好名称
    logModel->setHeaderData(0, Qt::Horizontal, tr("学生姓名"));
    logModel->setHeaderData(1, Qt::Horizontal, tr("书籍名称"));
    logModel->setHeaderData(2, Qt::Horizontal, tr("作者"));
    logModel->setHeaderData(3, Qt::Horizontal, tr("借出日期"));
    logModel->setHeaderData(4, Qt::Horizontal, tr("归还日期"));

    // 创建表格视图并绑定模型
    QTableView *logTableView = new QTableView(this);
    logTableView->setModel(logModel);
    // 可以让列宽自适应内容
    logTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

    // 把视图放到布局里
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(logTableView);
    setLayout(mainLayout);
}

3. 如果你坚持用QListView展示

因为ListView默认只显示单列,需要自定义委托来把多列数据拼接成一行展示,代码示例如下:

首先定义委托类:

#include <QStyledItemDelegate>
#include <QPainter>

class LogItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit LogItemDelegate(QWidget *parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // 获取当前行的所有列数据
        QString student = index.sibling(index.row(), 0).data().toString();
        QString bookName = index.sibling(index.row(), 1).data().toString();
        QString author = index.sibling(index.row(), 2).data().toString();
        QString issued = index.sibling(index.row(), 3).data().toString();
        QString returned = index.sibling(index.row(), 4).data().toString();

        // 拼接成友好的显示文本
        QString displayText = QString("学生: %1 | 书籍: %2(作者:%3) | 借出:%4 | 归还:%5")
                                  .arg(student).arg(bookName).arg(author).arg(issued).arg(returned);

        // 绘制文本
        QStyleOptionViewItem opt = option;
        initStyleOption(&opt, index);
        opt.text = displayText;
        QStyledItemDelegate::paint(painter, opt, index);
    }
};

然后在对话框构造函数里替换视图部分的代码:

// 替换原来的QTableView部分
QListView *logListView = new QListView(this);
logListView->setModel(logModel);
// 设置自定义委托
logListView->setItemDelegate(new LogItemDelegate(this));

QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(logListView);
setLayout(mainLayout);

4. 额外注意事项

  • 确保在应用启动时已经正确初始化SQLite连接,比如:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("book_system.db");
if (!db.open()) {
    qDebug() << "打开数据库失败:" << db.lastError().text();
}
  • 如果需要实时刷新日志列表,可以在添加/修改日志记录后,调用logModel->setQuery()重新执行查询来更新数据。

内容的提问来源于stack exchange,提问作者Hemil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:40:30