【问题标题】:QTableView is extremely slow (even for only 3000 rows)QTableView 非常慢(即使只有 3000 行)
【发布时间】:2011-05-01 04:16:05
【问题描述】:

我有一个 3000 行 8 列的表。我使用 QTableView。 要插入我所做的项目:

QStandardItem* vSItem = new QStandardItem();
vSItem->setText("Blabla");
mModel->setItem(row, column, vSItem);

其中 mModel 是 QStandardItemModel。 如果我没有太多行,一切都很好,但是当我试图想象大 数据(大约 3000 行),然后它非常慢(在 Win 7 64 位(8 核机器,8 GB RAM !!!)上为 20 秒)。 我可以做些什么来提高性能?

提前致谢。

【问题讨论】:

    标签: qt qtableview


    【解决方案1】:

    您是否对列或行的内容自动调整大小?有时它可能会成为性能杀手!

    看看这里: QHeaderView::ResizeToContents

    希望对你有帮助!

    【讨论】:

    • 不明确。除非默认情况下这样做,否则我没有。
    • 我拥有的是:mUi.mImagesTableView->setAlternatingRowColors(true); mUi.mImagesTableView->setSelectionMode(QAbstractItemView::SingleSelection); mUi.mImagesTableView->setSelectionBehavior(QAbstractItemView::SelectRows); mUi.mImagesTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); mUi.mImagesTableView->setIconSize(QSize(vIconSize, vIconSize)); mUi.mImagesTableView->setColumnWidth(0, vIconPlusBorder); mUi.mImagesTableView->horizo​​ntalHeader()->setStretchLastSection(true);
    • 尝试禁用 setStretchLastSection,禁用自动调整大小(我不记得它是否默认完成)...换句话说,尝试禁用可能与调整行和列大小相关的所有内容...在我的应用程序中,在发布时,我有一个包含超过 10,000 个项目的树视图(带有列),我可以毫无问题地调整所有内容...但是如果我打开这些自动调整大小功能,我的性能会严重下降!
    • 注意:即使在调试中,你也应该遇到少量数据的性能问题......
    • 随机想法:你在哪里创建数据?在一个被称为很多时间的方法中?
    【解决方案2】:

    我找到了解决方案:问题是我将模型分配给了 tableview 已经在构造函数中。所以每次我在模型中插入项目时, tableview 被告知并可能更新。现在我将模型分配给 只有在我用数据填充我的模型之后才能使用 tableview。 这不是一个优雅的解决方案,但它有效。有没有办法暂时 从 tableview 禁用模型或对 tableview 说的东西 不关心模型的变化?

    【讨论】:

    • 您可以尝试在模型上使用 blockSignals (doc.trolltech.com/main-snapshot/qobject.html#blockSignals),但这可能会让您更加头疼。确实,您应该考虑保持订单不变,或更改为您自己的模型(这样您就会知道何时说您已更改数据)。
    • 对于大型数据集,我会考虑编写一个“合适的”模型而不是使用 QStandardItemModel。在那里,您可以插入比单个项目更大的数据块,每个都会触发视图更新,这应该会大大提高性能。编辑:我看到我只是重复了詹姆斯在下面所说的话......
    【解决方案3】:

    对于这种数量的数据,您最好使用自定义模型 - 例如,您可以控制何时通知视图更新。由于现代硬件速度很快,“标准”项目可以扩展到数百甚至数千,但它们被明确记录为不适用于这种规模的数据集。

    【讨论】:

      【解决方案4】:

      此外,如果所有行的高度相同,则将 http://doc.qt.io/qt-5/qtreeview.html#uniformRowHeights-prop 设置为 true 可以提高性能。在我的例子中,包含大约 50.000 行的模型在 uniformRowHeights 设置为 false(默认值)时几乎无法使用。将其更改为 true 后,它就像一个魅力。

      【讨论】:

      • 这个函数是针对QTreeView的,这里说的是QTableView
      • 这样做速度几乎翻了一番!
      【解决方案5】:

      很好地调用自动调整列或行内容的大小。

      我有一个函数,每次客户端连接到我的服务器应用程序时都会向表中添加一列。随着表中的列数越来越多,插入时间似乎越来越长。

      我在做一个 ui->messageLog->resizeRowsToContents();每一次。我将其更改为仅自动调整正在添加的行的大小 ui->messageLog->resizeRowToContents(0);,然后缓慢消失了。

      【讨论】:

        【解决方案6】:

        我正在使用 80000 行,并且在向表中添加大量项目时遇到了类似的问题。

        我的解决方案是让它提前分配内存,告诉它需要多少行。

        我使用的是 Qtableview 和模型,所以:

        self.model.setRowCount(80000)

        我相信您可以将其与您的代码匹配

        【讨论】:

          【解决方案7】:

          试试这个:

                       QSqlDatabase db =QSqlDatabase::addDatabase( "QSQLITE");
          
                void SELECT_TO_TBLWID(QTableWidget * TBL, QString DbPath,QString SQL)
                            {
                                QSqlDatabase db2 =QSqlDatabase::database();
                                db2.setDatabaseName(DbPath);
                                if( !db2.open() )
                                {
                                  qDebug() << db2.lastError();
                                  qFatal( "Failed to connect." );
                                }
                                  QSqlQuery qry;
                                  qry.prepare(SQL);
                                  if( !qry.exec() )
                                    qDebug() << qry.lastError();
                                  else
                                  {
                                     QSqlRecord rec = qry.record();
          
                                       TBL->setColumnCount(rec.count());
                                       int RW=0;
                                       for( int r=0; qry.next(); r++ )
                                          {RW++;}
                                          TBL->setRowCount(RW);
                                          for (int pr=RW;qry.previous();pr--){// do nothing}
          
                                   for( int r=0; qry.next(); r++ )
                                      {
          
                                        for( int c=0; c<rec.count(); c++ )
                                        {
                                            if ( r==0)
                                            {
                                                TBL->setHorizontalHeaderItem(c,new QTableWidgetItem(rec.fieldName(c)));
                                            }
          
                                        TBL->setItem(r, c, new QTableWidgetItem(qry.value(c).toString()));
          
                                        }
          
                                      }
                                  }
          
                                  db2.close();
                           }
          

          【讨论】:

          • 虽然此代码可能有助于解决问题,但它并没有解释为什么和/或如何回答问题。提供这种额外的背景将显着提高其长期价值。请edit您的答案添加解释,包括适用的限制和假设。
          【解决方案8】:

          注意 setSectionResizeMode()。这对我有巨大的性能影响。每次修改都会导致行和列大小重新计算(即每个 setData()/setText() 调用)。在我达到 1000 多行之前,这并不明显。考虑改用 resizeSections(),这似乎是一次性调整。

          【讨论】:

            猜你喜欢
            • 2015-10-03
            • 2013-04-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-02
            相关资源
            最近更新 更多