PDA

View Full Version : QTreeWidget performance after QtConcurrent



ujwala
7th May 2013, 16:44
Hi,

I am using QtConcurrent for a function to process number of objects in batch.
For e.g. I have 1000 graphics objects, I call process() for 500 items and another call for remaining 500 items using two calls of QtConcurrent::run(...).
I get good performance improvement here. But after process() function I use these processed items to populate items in QTreewidget.
The time required to populate the QTreeWidget tremendously increases as compared to the time required for populating before we used QtConcurrent.


I have a XML file which contains details of each of these items which includes id, position, height, width. My application reads this file and pass this detail to process() to creates the Item class objects.



class Item :: QGraphicsObject
{
QString m_sId;
int m_iHeight, m_iWidth;
QPoint m_position;
};

// process()
process(int iStart, int iEnd, <list of XMLNode>)
{
for(iStart to iEnd)
{
// Read XMLNode and create Item object using the read details
}
}

// read()

read()
{
// Read the XML File
QList<XMLNode> lstNodes = readXML();

// call process() for list of XMLNode
QList<Item*> lstItems = process(1, lstNodes.size(), lstNodes);

// Add these items to scene using m_scene->addItem((QGraphicsItem*) item);

// Iterate through the list of items and add each of the item to QTreeWidget
for(i = 0 to size )
{
Item* item = lstItems1.at(i);
QTreeWidgetItem *treeItem = new QTreeWidgetItem(Items);
treeItem->setText(0, tr(item->m_sId));
}
}



Below is the modified code using QtConcurrent::run()



// process()
QList<Item*> process(int iStart, int iEnd, <list of XMLNode>)
{
QList<Item*> lstItems;
for(iStart to iEnd)
{
// Read XMLNode and create Item object using the read details
// Move the created graphics object on main thread as it needs to be added to scene later
item.moveToThread(QApplication::instance()->thread());
}
return lstItems;
}

read()
{
// Read the XML File
QList<XMLNode> lstNodes = readXML();

// call process() for list of XMLNode
int iSize = lstNodes.size();

QFutureSynchronizer<QList<Item*>> synchronizer;

QFuture<QList<Item*>> future1 = QtConcurrent::run(this, &Reader::process, 1, iSize/2, lstNodes);
QFuture<QList<Item*>> future2 = QtConcurrent::run(this, &Reader::process, iSize/2, iSize, lstNodes);

synchronizer.addFuture(future1);
synchronizer.addFuture(future2);

synchronizer.waitForFinished();

QList<Item*> lstItems1 = future1.result();
QList<Item*> lstItems2 = future2.result();

lstItems1.append(lstItems2);

// Add these items to scene using m_scene->addItem((QGraphicsItem*) item);

// Iterate through the list of items and add each of the item to QTreeWidget
for(int i = 0; i<= size; i++ )
{
Item* item = lstItems1.at(i);
QTreeWidgetItem *treeItem = new QTreeWidgetItem(treeWidget);
treeItem->setText(0, tr(item->m_sId));
}
}



My problem is, previously populating the TreeWidget was taking less time (1.9 sec) for 1000 items but now when I used QtConcurrent for process(), it has been increased (21.5 sec) whereas calling process() using QtConcurrent takes less time.

Can you please guide me resolving this issue?

wysota
7th May 2013, 21:13
Don't items one by one but rather do that in batches. For this you'll probably have to implement your own model and use QTreeView instead of QTreeWidget.

ujwala
8th May 2013, 12:06
Thanks Wysota.

Yes, I am planning to use QTreeView. But my concern here is the time has been substantially increased after i used QtConcurrent. Is that I have done something wrong here?

wysota
8th May 2013, 13:42
I don't think this is caused by QtConcurrent. For instance line #35 of your code snippet does not make much sense and also line #40 is simply invalid (you should get a segfault once i == size. My wild guess would be that your tree widget's header is set to adjust its width to its contents which is very slow if you keep adding items one by one.