在其他计算机上,QTableView 滚动缓慢

3
我正在使用Qt和C++开发一个数据库浏览应用程序。数据库位于我们的内部网络中。 我正在Win7 32位上工作和编译,使用Qt 4.7.3 + qodbc驱动程序。 我的项目目标是使这些数据对我们的人员可用,即使他们在旅途中,在这种情况下使用VPN。 连接非常缓慢(我的意思是:非常缓慢)。
因此,我有一个QTableView,其中填充了2k个结果。我只需要支持win7,并且在我们公司的电脑上运行良好,这些电脑位于网络中。 但是在某些计算机上,事情确实很慢,例如在我的QTableView上滚动。似乎只会在使用VPN时发生。我用于填充我的QTableView的方法仅是执行setQuery()。 因此,我想知道是否在查询执行后执行了一些网络操作?如果是这样,问题可能是什么? 我无法在Google或Qt文档中找到任何答案。
编辑:问题似乎直接来自QSqlQuery。我已经实现了以下模型作为避免无用查询的试验(是的,它很快且肮脏):
class SqlAsyncModel : public QSqlQueryModel
{
public:
  explicit SqlAsyncModel(QObject *parent = 0) : QSqlQueryModel(parent)  {}
  SqlAsyncModel(QSqlQueryModelPrivate &dd, QObject *parent)
              : QSqlQueryModel(dd, parent)      {}

  void    queryChange()       { _currRow = 0; qu = this->query(); qu.last(); }
  virtual QVariant    data(const QModelIndex &index, int role = Qt::DisplayRole)
  {
      int r = index.row(); int c = index.column();
      if(!index.isValid() || role & ~Qt::DisplayRole || r < 0 || c < 0)
         return QVariant();
      while (_currRow < r)
         if (!nextValue())   goto ret;
      while (_currRow > r)
         if (prevValue())    goto ret;
  ret: return (qu.record().value(c));
  // Returns value or QVariant() if invalid QSqlRecord
  }
private:
  inline bool nextValue() { _currRow++; return qu.next(); }
  inline bool prevValue() { _currRow--; return qu.previous(); }
  int         _currRow;
  QSqlQuery   qu;

这仍然给我相同的行为。

注意:我也使用:

while (mySqlAsyncModel->canFetchMore())
    mySqlAsyncModel->fetchMore();

尝试在出现问题的机器上运行Wireshark,并查看用户滚动时发送/接收的网络流量(如果有)。结果可能会很有启发性。 - Jeremy Friesner
谢谢您的建议。在尝试之后,我发现我的QTableView在每次滚动/窗口出现时都会刷新项目,这显然是问题的根源。 似乎在QTableView中没有办法设置类似于刷新计时器的东西。我去看看其他的小部件... - Geod24
我认为QTableView类很好,但是你可能需要替换成一个更适合你目的的不同的QAbstractTableModel子类(而不是你现在可能正在使用的普通QSqlQueryModel对象)。这篇文章可能会引起你的兴趣:http://blog.wysota.eu.org/index.php/2006/12/26/remote-models/ - Jeremy Friesner
这可能会有帮助:http://www.linuxjournal.com/article/9602 - Jeremy Friesner
有趣的链接。它让我深入挖掘MVC架构,并学到了很多我之前不知道的东西。然而,它似乎并不真正符合我的需求。 默认情况下,我的查询从服务器检索256个结果(现在我正在使用fetchMore())。我可以在15到20秒内获取所有结果(使用fetchMore()),这对我的客户来说是可以接受的。但是在滚动时,会执行额外的查询,这才是真正的问题。 另一个问题是,由于这种实时更新的行为,关闭与数据库的连接会导致模型清除。 - Geod24
1个回答

2
因此,问题出在QODBCResult的行为上。 我下载了Qt的源代码,并编辑了odbc驱动程序。 对于那些感兴趣的人,你需要更改QODBCResult :: data(int)的行为,至少还有QODBCResult :: fetch(int)(如果你真的想要更干净的东西,可能还有QODBCResult :: fetchprevious / next / last / first函数)。
我个人添加了一个QList缓冲区,在请求时存储我的行。这与Qt的行为几乎相同(因为它不会缓存所有内容,而只缓存请求的行)。我的应用程序在内存中占用38-40 Mbs,其中包含22k行/ 55列文本和浮点数缓存。

那么为什么现在还没有解决这个问题呢?在我看来,由于提供的工件质量问题,应该已经实现了请求行的简单缓存。例如,我有一个简单的查询,加载50行5列,并且与此模型链接的每个视图都非常缓慢。我应该实现自己的模型并在本地缓存数据,但是对于50行,为什么我不能使用标准模型并完成它,并且至少知道我的用户不会抱怨只有50行的性能缓慢。 - Paul-Sebastian Manole
我猜那是一个你需要在Qt论坛/邮件列表上问的问题 ;) - Geod24
似乎视图是问题所在。通过在模型中插入一些调试打印,我可以看到每次与视图交互并且不仅限于可见索引的所有索引都会调用data成员函数以检查各种角色的新数据。将数据缓存到快速数据结构中可以减轻延迟,但是函数调用仍然像以前一样频繁,只是返回时间更短了。应该在视图内部进行进一步改进以实现虚拟化。 - Paul-Sebastian Manole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接