QTableView +自定义TableModel +延迟加载

Art*_*m E 6 qt

我需要将大量数据集加载到QTableView中.数据集在内存中不低于700Mb,我不想将其全部加载到内存中.

由于两个原因,QSqlQueryModel对我来说并不理想 - 它不可编辑,并且不是真正按需加载(因为将整个数据提取到内存中).

我想得到什么

  • 我想只将部分数据存储在内存中.仅用于显示和快速滚动的缓冲区.
  • 模型应该是可编辑的
  • 它应该是低内存消耗
  • 应该没有冻结

我是如何解决这个问题的(我的代码的简单模型)

  1. 自定义QTableView(tableView)
  2. 自定义TableModel(型号)
  3. 模型包装.(包装)

模型包装器从数据库中选择行数,并将此值设置为模型.现在模型可以回答int rowCount().

为tableView.verticalScrollBar()设置了相同的值.

tableView.verticalScrollBar信号(valueChanged)连接到tableview槽(on_valueChanged)

一些代码

tableView::on_valueChanged(value)
{
  wrapper.changeOffset(value);
}

wrapper::changeOffset(value)
{
  if (_offset == value){
    return;
  }

  _selectQuery->seek(value);    
  int endValue = qMin(value + _cacheSize, model->rowCount());  
  _list.clear();
  for(int i = value; i < endValue-1; i++){      
    _list.append(_selectQuery->record());
  }
  model->setRecordList(_list);
  _offset = value;
  model->setOffset(_offset);
Run Code Online (Sandbox Code Playgroud)

}

包装器中的_selectQuery :: changeOffset是用于选择查询结果的PRSqlQuery游标.

我还在模型中实现了几种方法

QVariant SqlRecModel::data(const QModelIndex &index, int role) const
{
    int row = index.row() - _offset;        
    if (row > m_recList.size() || row < 0){
        return QVariant();
    }
    if (role == Qt::DisplayRole)
    {
        QVariant value = m_recList.at(row).value(index.column());
        return value;
    }
    return QVariant();
}
Run Code Online (Sandbox Code Playgroud)

用于模型数据存储的Setter

void SqlRecModel::setRecordList(const QList<QSqlRecord> &records)
{
    qDebug() << "r:";
    emit layoutAboutToBeChanged();
    m_recList = records;
    emit layoutChanged();
}
Run Code Online (Sandbox Code Playgroud)

问题

我可以滚动_cacheSize行,但是在离开旧的cacheRange之后我崩溃了(程序意外地完成了.).

有什么建议?我不知道在哪里挖.谢谢!

Art*_*m E 0

对不起打扰。

错误出现在其他代码块中。

这个方法刚好可以解决我的任务。

顺便说一句:如果您使用缓存缓冲区,您可以实现更平滑的滚动。