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

QTableView闲置一段时间后空白问题求助

问题分析与解决方案

看起来你遇到了一个典型的Qt数据库连接和对象生命周期问题,我来帮你一步步拆解并解决:

1. 核心问题拆解

(1)错误创建MainWindow局部实例

你代码里的MainWindow conn;是关键问题——这会生成一个临时的MainWindow对象,当这段代码所在的函数执行完毕后,这个临时对象会被销毁,它持有的数据库连接(conn.mydb)也会跟着关闭或失效。哪怕你一开始查询成功给模型塞了数据,后续连接失效后,模型可能无法维持数据显示;而且每次刷新时重新创建临时对象打开连接,很容易出现连接状态不一致的问题。

(2)未检查查询执行结果

你调用qry->exec()后没有判断是否执行成功,如果闲置后数据库连接超时断开,查询会默默失败,模型没有数据,表格自然就空白了,你还完全不知道问题出在哪。

(3)内存泄漏+模型生命周期混乱

每次执行这段代码都会new新的QSqlQueryModel和QSqlQuery,但之前的模型没有被释放,虽然这不是空白的直接原因,但会慢慢占用内存;而且局部创建的模型如果没指定父对象,还可能出现野指针风险。


修正后的代码示例

假设这段代码是你MainWindow类里的刷新按钮槽函数,我帮你调整成正确的写法:

void MainWindow::on_refresh_btn_clicked()
{
    // 先检查当前数据库连接是否有效,无效则重新打开
    if (!mydb.isOpen()) {
        if (!connOpen()) {
            ui->label_sec_status->setText("<font color='red'>Failed to Open Database</font>");
            qDebug() << "重新连接失败:" << mydb.lastError().text();
            return;
        }
        ui->label_sec_status->setText("<font color='green'>Connected</font>");
    }

    // 先清理旧模型,避免内存泄漏
    delete ui->tableView->model();
    delete ui->combo_BUSN_MNGR->model();
    delete ui->combo_SP_NAME->model();

    // 给模型指定父对象(当前窗口),Qt会自动管理内存,不用手动delete
    QSqlQueryModel *modal = new QSqlQueryModel(this);
    QSqlQueryModel *modal2 = new QSqlQueryModel(this);
    QSqlQueryModel *modal3 = new QSqlQueryModel(this);

    // 使用栈上的QSqlQuery对象,不用手动释放,更安全
    QSqlQuery qry(mydb);
    QSqlQuery qry2(mydb);
    QSqlQuery qry3(mydb);

    // 执行查询并检查结果
    qry.prepare("select top 100 * from [dbo].[LOG] order by DEAL_NO DESC");
    if (!qry.exec()) {
        qDebug() << "LOG表查询失败:" << qry.lastError().text();
        ui->label_sec_status->setText("<font color='red'>Query Failed</font>");
        return;
    }

    qry2.prepare("select MNGR from [dbo].[Staff]");
    if (!qry2.exec()) {
        qDebug() << "Staff表查询失败:" << qry2.lastError().text();
        ui->label_sec_status->setText("<font color='red'>Query Failed</font>");
        return;
    }

    qry3.prepare("select SalesP from [dbo].[Sales]");
    if (!qry3.exec()) {
        qDebug() << "Sales表查询失败:" << qry3.lastError().text();
        ui->label_sec_status->setText("<font color='red'>Query Failed</font>");
        return;
    }

    modal->setQuery(qry);
    modal2->setQuery(qry2);
    modal3->setQuery(qry3);

    // 检查模型是否获取到数据
    if (modal->rowCount() == 0) {
        qDebug() << "LOG表查询无数据返回";
        ui->label_sec_status->setText("<font color='orange'>No Data</font>");
    }

    // 绑定模型到控件
    ui->tableView->setModel(modal);
    ui->tableView->resizeColumnsToContents();
    ui->tableView->setAlternatingRowColors(true);
    ui->tableView->setStyleSheet("alternate-background-color: #99ceff; background-color: #f2f2f2;");

    ui->combo_BUSN_MNGR->setModel(modal2);
    ui->combo_SP_NAME->setModel(modal3);

    qDebug() << "LOG表返回行数:" << modal->rowCount();
}

额外优化建议

  1. 统一管理数据库连接:不要每次查询都临时创建MainWindow对象,直接用当前窗口的mydb成员变量和connOpen()方法;最好把数据库连接封装成单例类,整个程序只用一个连接实例,避免连接混乱。
  2. 模型复用优化:如果刷新频率不低,可以在MainWindow的构造函数里初始化这些模型,每次刷新时只调用setQuery()更新数据,不用反复创建新模型,效率更高。
  3. 监听连接状态:有些数据库服务器会自动断开长时间闲置的连接,你可以在程序里定期检查连接有效性,或者监听QSqlDatabase的相关信号,自动重连。
  4. 始终检查操作结果:数据库操作(连接、查询)都要检查返回值,并用lastError()获取错误信息,这样排查问题会快很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:54:05