QTableView dataChanged 不响应或耗费很多大量CPU资源的一种情况及解决思路

之前有人提到不响应有可能是信号发送方和QTableView不在同一个线程,出现跨线程问题,解决方法就是通过另一个信号中转一下,反正最后在同一个线程(差不多就是gui线程)发射dataChanged信号即可。

这里说QTableView dataChanged 耗费很多大量CPU资源的另一种情况。

This signal is emitted whenever the data in an existing item changes.
If the items are of the same parent, the affected ones are those between topLeft and bottomRight inclusive. If the items do not have the same parent, the behavior is undefined.
此段引用跟本文无关。。。

看源代码(Qt5.9.9)就知道有多坑,粗暴。 其中官方吐槽,最为致命(我知道但我就是不改)。函数文档很丰满,实际实现很骨感。


void QAbstractItemView::update(const QModelIndex &index)
{
    Q_D(QAbstractItemView);
    if (index.isValid()) {
        const QRect rect = visualRect(index);
        //this test is important for peformance reason
        //For example in dataChanged we simply update all the cells without checking
        //it can be a major bottleneck to update rects that aren't even part of the viewport
        if (d->viewport->rect().intersects(rect))
            d->viewport->update(rect);
    }
}

void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    Q_UNUSED(roles);
    // Single item changed
    Q_D(QAbstractItemView);
    if (topLeft == bottomRight && topLeft.isValid()) {
        const QEditorInfo &editorInfo = d->editorForIndex(topLeft);
        //we don't update the edit data if it is static
        if (!editorInfo.isStatic && editorInfo.widget) {
            QAbstractItemDelegate *delegate = d->delegateForIndex(topLeft);
            if (delegate) {
                delegate->setEditorData(editorInfo.widget.data(), topLeft);
            }
        }
        if (isVisible() && !d->delayedPendingLayout) {
            // otherwise the items will be update later anyway
            update(topLeft);
        }
    } else {
        d->updateEditorData(topLeft, bottomRight);
        if (isVisible() && !d->delayedPendingLayout)
            d->viewport->update();
    }

#ifndef QT_NO_ACCESSIBILITY
    if (QAccessible::isActive()) {
        QAccessibleTableModelChangeEvent accessibleEvent(this, QAccessibleTableModelChangeEvent::DataChanged);
        accessibleEvent.setFirstRow(topLeft.row());
        accessibleEvent.setFirstColumn(topLeft.column());
        accessibleEvent.setLastRow(bottomRight.row());
        accessibleEvent.setLastColumn(bottomRight.column());
        QAccessible::updateAccessibility(&accessibleEvent);
    }
#endif
    d->updateGeometry();
}

似乎只能一个格子一个格子emit dataChanged(实属无奈),此方法确实可以降CPU资源占用,有空继承重写下吧(纯粹空想)。或许Qt高版本就修好了(实际并没有)?

void TableModel::UpdateView(int top, int bottom, int Left, int Right)
{
    //emit dataChanged(index(top, Left), index(bottom, Right), roles);两个index不相等会导致全屏刷新
    int row, column;
    for (row = top; row <= bottom; row++) {
        for (column = Left; column <= Right; column++) {
            auto it = index(row, column);
            emit dataChanged(it, it);//roles官方忽略,坑
        }
    }
}

如果有帮助请点赞,有更好方法欢迎留言。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值