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

为什么在线程中更新QTableView的model时界面无法自动刷新?

问题原因

Qt中所有GUI相关对象(包括QStandardItemModel这类数据模型)都属于主线程对象,不支持跨线程直接操作。你在子线程中直接调用setData更新数据时,模型发出的更新通知无法正常触发UI线程的重绘逻辑,只有当UI触发重绘事件(比如点击单元格、窗口重绘)时才会显示最新值。

解决方法

推荐使用Qt的跨线程信号槽机制完成数据更新,这是Qt官方推荐的跨线程UI操作方案,实现步骤如下:

步骤1:修改Loop_terminal类定义

在类的signals段新增数据更新信号:

class Loop_terminal : public QThread
{
    Q_OBJECT
    // 其他原有定义保持不变
signals:
    void dataUpdated(int row, int col, QVariant value);
};

步骤2:修改子线程的run函数,不再直接操作model,改为发射信号

void Loop_terminal::run(){
    while(1){
        if(j1939->ID_and_data_is_updated){
            j1939->ID_and_data_is_updated = false;
        }
        // 直接发射信号,把要更新的位置和数据传输出去
        emit dataUpdated(1, 1, this->i);
        i++;
        msleep(1000);
    }
}

步骤3:在主线程中连接信号槽,在槽函数中执行model更新

在你创建Loop_terminal实例的代码处,新增信号槽连接:

/* Threads */
this->loop_terminal = new Loop_terminal(j1939, &start_loop_terminal_thread, looping_terminal_model);
// 新增信号槽连接
connect(loop_terminal, &Loop_terminal::dataUpdated, this, [=](int row, int col, QVariant value){
    QModelIndex index = looping_terminal_model->index(row, col, QModelIndex());
    looping_terminal_model->setData(index, value);
    // 如果还是没有自动刷新可以加下面这行手动触发数据变更通知
    // looping_terminal_model->dataChanged(index, index);
});
loop_terminal->start();

其他可选方案

如果你不想新增信号,也可以用QMetaObject::invokeMethod直接在子线程中调用主线程的方法执行更新:

// 在run函数中替换原来的setData逻辑
QMetaObject::invokeMethod(looping_terminal_model, [=](){
    QModelIndex index = looping_terminal_model->index(1,1,QModelIndex());
    looping_terminal_model->setData(index,this->i);
}, Qt::QueuedConnection);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:09:04