[PyKDE] QButton/QGridLayout woes

David K. Hess dhess at verscend.com
Tue Sep 20 19:51:55 BST 2005

If I interpret "the threaded object makes calls into my QT class"  
correctly, then this definitely could be the root of your problem.  
While you may have one thread dedicated to running the Qt Application  
object's event loop, the restriction documented by Trolltech  
restricts you from calling *any* of the Qt GUI API from another  
thread. That means that if your threaded object makes a call to your  
Qt class and that call results in any of the Qt API being invoked  
(which your example indicates that it does) then you aren't  
guaranteed proper behavior.

The recommended method is to use QApplication:postEvent() (which is  
thread safe) to send an event to the Qt object that your threaded  
object is trying to manipulate. Then the QApplication's thread will  
deliver the event in the event loop and the operations you are trying  
to perform can be safely executed by QApplication's thread.


On Sep 20, 2005, at 1:07 PM, Hoka ME Tichenci wrote:

> What I mean from a multithreaded application is that the threaded  
> object makes calls into my QT class, and the QT class modifies the  
> widgets accordingly (the qt app is single threaded). The given code  
> was within the QT application. Originally this didn't work because  
> the PyQT I was using was based on SIP3 (which caused lockups in  
> this exact scenario), but I should now be using a SIP4 release  
> (3.14.1 edu). I'm also using a locking mechanism so that this code  
> should run completely before it can be run again (so it should be  
> threadsafe). I think its odd because the message box will pop up if  
> I construct it, but trying to add the button doesn't work.
> -Hoka
>> You mention "from a multithreaded application". Are you being careful
>> to keep all Qt activity exclusively in one thread? From http://  
>> doc.trolltech.com/3.3/threads.html:
>> ----
>> In Qt, one thread is always the GUI or event thread. This is the
>> thread that creates a QApplication object and calls  
>> QApplication::exec (). This is also the initial thread that calls  
>> main() at program
>> start. This thread is the only thread that is allowed to perform GUI
>> operations, including generating and receiving events from the window
>> system. Qt does not support creating QApplication and running the
>> event loop (with QApplication::exec()) in a secondary thread. You
>> must create the QApplication object and call QApplication::exec()
>> from the main() function in your program.
>> Threads that wish to display data in a widget cannot modify the
>> widget directly, so they must post an event to the widget using
>> QApplication::postEvent(). The event will be delivered later on by
>> the GUI thread.
>> ----
>> My guess would be that two threads got into Qt at the same time. It
>> may not happen under Linux due to timing differences.
>> Dave
>> On Sep 18, 2005, at 10:07 PM, Hoka ME Tichenci wrote:
>>> I'm having an odd issue with Windows PyQt 3.14.1 Educational, the
>>> code is supposed to dynamically add/remove buttons when called from
>>> a multithreaded application. On Linux (PyQt 3.13 qt 3.3.4) the code
>>> runs fine, but on Windows I get assert problems in a rather odd  
>>> spot.
>>> The code is here (bgrid is a QGridLayout, bg_projectors is a
>>> QButtonGroup):
>>> print "adding projector rnode: %s" % rnode.getName()
>>> attrs = rnode.getAttributes()
>>> print "xpos: %s ypos: %s" % (attrs["xpos"],attrs["ypos"])
>>> tmp = QPushButton(self.bg_projectors,"yes")
>>> tmp.setText(rnode.getName())
>>> print "qpushbutton built"
>>> self.bgrid.addWidget(tmp,attrs["ypos"],attrs["xpos"])
>>> print "widget added"
>>> tmp.show()
>>> print "Done adding projector!"
>>> However, when run I get this output:
>>> adding projector rnode: Projector: BigOne
>>> xpos: 1 ypos: 1
>>> qpushbutton built
>>> projector is off
>>> widget added
>>> Done adding projector!
>>> ASSERT: "src_dc && dst_dc" in kernel\qpaintdevice_win.cpp (388)
>>> What's odd is that the ASSERT failure is at the end, after the
>>> method should be done and printed its last statement. Furthermore,
>>> if I make a QWarningBox or other similar piece of code pauses the
>>> system after tmp.show() is called, the QButton can be seen in the
>>> background, after the box is closed the button disappears, but
>>> oddly enough no ASSERT is thrown. This may not be the right way to
>>> do something like this, and if it isn't correct me, but I'm at a
>>> lost and Google didn't return anything worthwhile.
>>> Thanks for your time,
>>> -Hoka
> _______________________________________________
> PyKDE mailing list    PyKDE at mats.imk.fraunhofer.de
> http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

More information about the PyQt mailing list