我的代码很简单,就是在主线程中直接调用这个函数,原先的代码是这样的,在QT4里工作的很好:
void TableModel::updateData(int i)
{
if (i<0) return;
// 根据指定行列,得到index
QModelIndex t1 = index(i, 0);
QModelIndex t2 = index(i, 5);
qDebug() << "111_____TableModel::updateData " << i; // 后台打印进度条数据正确
emit dataChanged(t1, t2); // view 系统自带信号,会导致刷新数据
}
但是以上代码在QT5里不工作,但是官方文档说dataChanged的新增第三个参数等于0就所有角色都刷新,我怀疑它说反了,所以就改成了这样:
void TableModel::updateData(int i)
{
if (i<0) return;
// 根据指定行列,得到index
QModelIndex t1 = index(i, 0);
QModelIndex t2 = index(i, 5);
qDebug() << "111_____TableModel::updateData " << i;
QVector<int> qq;
qq.append(Qt::DisplayRole);
qq.append(Qt::DecorationRole);
qq.append(Qt::EditRole);
qq.append(Qt::ToolTipRole);
qq.append(Qt::StatusTipRole);
qq.append(Qt::WhatsThisRole);
qq.append(Qt::SizeHintRole);
qq.append(Qt::AccessibleTextRole);
qq.append(Qt::AccessibleDescriptionRole);
qq.append(Qt::UserRole);
emit dataChanged(t1, t2, qq);
}
结果还是不行。
于是没办法,又在主线程里尝试调用另一个函数:
void TableModel::refrushModel()
{
beginResetModel(); // view 内置函数,这句是最关键的,可导致view刷新
endResetModel();
emit updateCount(this->rowCount(QModelIndex())); // 入口,在model里发信号广播。
}
这下进度条终于刷新了,因为调用beginResetModel和endResetModel后,整个table的数据都被刷新了。这样做有3个坏处:
1. 效率很低,我不需要刷新整个table
2. 整体刷新导致鼠标选中某一行信息丢失
3. 进度条走到最后99%的时候。。。居然还是程序会不响应。。。(虽然是死机,但我觉得不是我的问题,QT4里在找到emit datachanged方法之前也曾这样做过,但没有死机的现象)
所以整体刷新的方案不可取。
正常的逻辑是emit dataChanged(t1, t2, qq);后,QT框架应该会自动调用我重写的void QStyledItemDelegate::paint()函数,现在初步怀疑是QT5里没有把datachanged信号与paint函数联系起来,或者文档说明哪里有遗漏?
另外有一个疑点是,我其实是间接在多线程里(但上了锁的,应该不会有问题,只是我对UI线程的理解还不够深刻,第二个线程直接更新UI界面这样对吗)调用TableModel::updateData(int i),也可能导致潜在的UI问题。但是毕竟这个问题在QT4下从来没有出现过,而QT5下每次都出错,我想应该不是QT5的多线程改变后的结果吧(也没听说QT5对多线程有什么改动)。