QTableView非常慢(即使只有3000行)
我有一个3000行8列的表格。我使用QTableView。 要插入项目,请执行以下操作:QTableView非常慢(即使只有3000行),qt,qtableview,Qt,Qtableview,我有一个3000行8列的表格。我使用QTableView。 要插入项目,请执行以下操作: QStandardItem* vSItem = new QStandardItem(); vSItem->setText("Blabla"); mModel->setItem(row, column, vSItem); QSqlDatabase db =QSqlDatabase::addDatabase( "QSQLITE"); void SELECT_
QStandardItem* vSItem = new QStandardItem();
vSItem->setText("Blabla");
mModel->setItem(row, column, vSItem);
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();
}
其中mModel是QStandardItemModel。
如果我没有太多的行,一切都很好,但是当我试图想象大的时候
数据(大约3000行),然后速度非常慢(在Win7 64位(8核机器,8GB内存!!!)上20秒)。
我能做些什么来提高绩效
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();
}
提前谢谢。您有自动调整列或行内容大小的功能吗?有时它可能是性能上的杀手
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();
}
请看这里:
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();
}
希望有帮助 我找到了一个解决方案:问题是我将模型分配给了tableview
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();
}
已在构造函数中。所以每次我在模型中插入项目,
tableview已通知,可能已更新。现在,我将模型指定给
只有在我用数据填充模型后才能查看tableview。
这不是一个优雅的解决方案,但它是有效的。有没有办法暂时
禁用tableview中的模型或对tableview说要
不关心模型中的更改吗?对于这种数量的数据,最好使用自定义模型-然后您可以控制何时通知视图更新,例如。由于现代硬件速度快,“标准”项可以扩展到数百个,甚至数千个,但它们被明确记录为不适用于这种大小的数据集。此外,如果所有行的高度相同,设置为true可以提高性能。在我的例子中,一个包含大约50000行的模型在uniformRowHeights设置为false(默认值)时几乎不可用。将其更改为true后,它就像一个符咒一样工作。很好地调用了自动调整列或行内容大小的功能
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();
}
我有一个函数,每次客户端连接到我的服务器应用程序时,都会向表中添加一列。随着表中的列数越来越多,插入时间似乎越来越长
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();
}
我在做一个ui->messageLog->resizeRowsToContents();每一次。我将此更改为仅自动调整正在添加的行的大小ui->messageLog->resizeRowToContents(0);,速度变慢了。我正在使用80000行,在向表中添加大量项时遇到了类似的问题
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();
}
我的解决方案是让它通过告诉它需要多少行来提前分配内存
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();
}
我使用的是Qtableview和模型,因此:
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();
}
self.model.setRowCount(80000)
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();
}
我相信您可以将其与您的代码相匹配尝试以下方法:
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();
}
QSqlDatabase db=QSqlDatabase::addDatabase(“QSQLITE”);
void SELECT_TO_TBLWID(QTableWidget*TBL、QString DbPath、QString SQL)
{
QSqlDatabase db2=QSqlDatabase::database();
setDatabaseName(DbPath);
如果(!db2.open())
{
qDebug()设置行数(RW);
for(int pr=RW;qry.previous();pr--){//donothing}
for(int r=0;qry.next();r++)
{
对于(int c=0;csetHorizontalHeaderItem(c,新的QTableWidgetItem(rec.fieldName(c)));
}
TBL->setItem(r,c,新的QTableWidgetItem(qry.value(c.toString()));
}
}
}
close();
}
注意SETSECTION RESSIZMEDE()。这对我来说有很大的性能影响。它会导致每一个修改(即每个StEATDATA()/SETTATE())调用的行和列大小重算。直到我达到1000行时,这才是明显的。考虑使用RsisiSeSeX()。相反,这似乎是一次调整。
没有明确说明。除非按照默认设置进行调整,否则我没有它。我有的是:mUi.mImagesTableView->setAlternatingRowColor(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->horizontalHeader()->setStretchLastSection(true);尝试并禁用setStretchLastSection,禁用自动调整大小(我不记得是否默认完成了)…换句话说,尝试并禁用与调整行和列大小相关的所有内容…在我的应用程序中,在发行版中,我有一个树状视图(带列)有超过10000个项目,我可以毫无问题地调整所有内容的大小…但是如果我打开那些自动调整大小的功能,我的性能会下降得很糟糕!注意:即使在调试中,少量数据也会有性能问题…随机想法:在哪里创建数据?在一个称为“很多时间”的方法中?你可以尝试搞乱在模型上使用BulthSpults(),但这可能会给您带来更大的麻烦。真的,您应该考虑将订单保留相同,或者更改为您自己的模型(这样您就知道何时更改数据)。对于大型数据集,我会考虑写一个“适当的”。模型,而不是使用QStandardItemModel。在那里,你可以插入比单个项目更大的数据块,每个数据块都会触发视图更新,这将使我的性能大大提高。编辑:我看到我刚才重复了James在下面所说的……这个函数是针对QTreeView的,这里我们讨论的是QTableView,这样做的速度几乎是原来的两倍他的代码可能有助于解决问题,但没有解释为什么和/或如何回答问题。提供此附加上下文将显著提高其长期价值。请您的答案添加解释,包括适用的限制和假设。
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();
}