[Qt-interest] QGraphicsItem and Threads

Enrico Ros enrico.qt at email.it
Mon Oct 19 15:28:08 CEST 2009


On Monday 19 October 2009 15:14:14 Ole Streicher wrote:
> Hi,
> 
> I am trying to change lots of QGraphicsItems at once:
> 
> for item in self.items:
>     item.setBrush(QtGui.QBrush(QtGui.QColor(c[0], c[1], c[2]))
> 
> When I do this in the main loop, everything is OK (but the gui behaves
> not responsive during the loop). When I try to do this in an extra
> thread, the program crashes on
> 
> /usr/lib/libQtGui.so.4(_ZN6QBrush4initERK6QColorN2Qt10BrushStyleE+0x7d)[0x7
> f49b1f4424d] (is this the mangled QBrush constructor call?)
> 
> which I dont understand: At first, the Q[Abstract]GraphicsItems are not
> QObjects, so their creation should be possible not only in the thread
> where they are created. They also dont have a "moveToThread()" method so
> that I could transfer them to another thread. They also have no parent
> (which means that I should be able to transfer them without hassle) --
> even the scene they belong to is not a "parent".
> 
> At second, the crash seems to occur not in the setBrush() method, but in
> the constructor of QBrush -- that should not happen at all since the
> QBrush creation should be possible in any thread.
> 
> What is wron here? And how can I make huge graphical changes (100.000
> items) without getting my GUI unresponsive?

Hello Ole,
 the QBrush may allocate a QPixmap that is windowing-system dependant and 
cannot be created outside of the main thread. As a rule of thumb: only use 
QImages (or other non-gui classes) in threads.

About the QGraphicsItem crash: you never know what's behind the scene of the 
creation of the item. Maybe you have concurrency problems when it tries to 
access the scene, or any other kind of concurrency problem. Maybe it allocates 
a 'cache pixmap'.. so create them on the main thread only.

Techniques for making the gui responsive while creating the items:

 - if you have to load images, do it on threads and post a 'QImage *' to the 
main thread. there you'll be able to convert it to QPixmap, or QBrush or 
whatever

 - if you have to load 100'000 items, divide them into chunks of.. say.. 100 
items, and schedule the execution of the loading function with a zero-timer 
(to run the event-loop in between). Use for example:
  QTimer::singleShot(0, this, SLOT(createNextHundredItems()));

 - you can run QApplication::processEvents(), maybe excluding some kind of 
events while creating the items. However this approach of "nesting event 
dispatching" may lead to problems (for example if your object get deleted 
while driving the events processing)

 - see Qt Quarterly 27: http://doc.trolltech.com/qq/qq27-responsive-guis.html

Enrico Ros



More information about the Qt-interest-old mailing list