QT QtableModel 的fetchMore()具体怎么使用

  • QTableModel能够实现数据按需加载,从而实现“大数据或无限数据”的动态加载,避免卡顿

实现过程简析

  • QT提供了Model-View机制,来实现数据的管理和表格显示
  • View会在特定条件下,调用Model的接口,实现相关模型数据的调用,调用过程不会拷贝数据,提高存储和运行效率
  • rowCount()方法,作为model接口,被View调用,获得View要显示的总行数
  • QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const,作为model接口,被View调用,返回数据的值,返回类型是值
  • 当canFetchMore()被调用且返回值为true时,View会调用fetchMore(),更新View后续操作
  • 在Qt中,canFetchMore()的调用机制与模型的数据加载策略密切相关其触发条件及核心逻辑如下
    • 视图驱动加载​,需要展示更多数据时,Qt框架会自动检测当前模型是否还有未加载的数据
      • 滚动到底部​:用户滚动到视图底部时,框架会调用canFetchMore()判断是否需要加载新数据。
      • 树形结构展开​:对于树形模型(如QTreeView),展开父节点时会触发canFetchMore(),检查该节点下是否有更多子数据。
    • 模型数据状态判断,重写canFetchMore(),通过自定义逻辑返回true或false,决定是否触发fetchMore()加载数据
      • 分页数据未完全加载​
      • ​数据库查询剩余数据​
    • 显示调用,手动触发fetchMore(),此时会隐式调用canFetchMore()进行验证
      • 若需一次性获取全部数据:(如导出到文件)while (model->canFetchMore()) {}
      • 后台预加载:在数据请求完成前预加载部分数据,优化用户体验
    • 与UI交互的联动,滚动到底部时,通过QScrollEvent触发fetchMore()

QT官方示例分析(fetchmore)

int FileListModel::rowCount(const QModelIndex &parent) const
{
    return parent.isValid() ? 0 : fileCount; // 获得Model与View交互部分的长度
}
// 若当前交互长度小于数据列表总长度,则可以加载更多
// 合适加载,取决于View的策略,若不重写,则总是返回false
bool FileListModel::canFetchMore(const QModelIndex &parent) const
{
    if (parent.isValid())
        return false;
    return (fileCount < fileList.size()); 
}
// 当滑动到末尾等条件下,会触发该函数,此处的操作是将交互部分长度:fileCount+=100
// 随后View在刷新界面时,会调用data()函数,渲染新的数据
void FileListModel::fetchMore(const QModelIndex &parent)
{
    if (parent.isValid()) return;
    int remainder = fileList.size() - fileCount;
    int itemsToFetch = qMin(100, remainder);
    if (itemsToFetch <= 0) return;
    beginInsertRows(QModelIndex(), fileCount, fileCount + itemsToFetch - 1);
    fileCount += itemsToFetch; // 
    endInsertRows();
    emit numberPopulated(itemsToFetch);// 发送信号,通知UI进行一些状态显示
}
void FileListModel::setDirPath(const QString &path)
{
    QDir dir(path);
    beginResetModel();
    fileList = dir.entryList();// 隐式共享,不会拷贝数据
    fileCount = 0;
    endResetModel();
}
//*****************************************************************************************//
QVariant FileListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())  return QVariant();

    if (index.row() >= fileList.size() || index.row() < 0)  return QVariant();

    if (role == Qt::DisplayRole) {
        return fileList.at(index.row()); //at()返回的是const,是隐式共享,不会拷贝数据
    } else if (role == Qt::BackgroundRole) {
        int batch = (index.row() / 100) % 2;
        if (batch == 0)
            return qApp->palette().base();
        else
            return qApp->palette().alternateBase();
    }
    return QVariant();
}
// 看一下at()的原型:
inline const T &QList<T>::at(int i) const //返回:const T &
{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range");
 return reinterpret_cast<Node *>(p.at(i))->t(); }
// 底层转换,直接转换指针类型,并返回,因此返回的实际是Node *的引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HardBeans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值