为什么在线程中更新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
相关产品推荐
相关产品推荐

