[PyKDE] PyQt4 Questions

Detlev Offenbach detlev at die-offenbachs.de
Sat Mar 18 16:11:04 GMT 2006


Am Samstag, 18. März 2006 16:29 schrieb Giovanni Bajo:
> Detlev Offenbach <detlev at die-offenbachs.de> wrote:
> > I have a dialog, that creates a new dialog and shows it. The code is like
> >
> > self.dlg = MyDialog(self)
> > dlg.show()
>
> MyDialog is a QObject, and it is constructed as child of self. Its lifetime
> becomes bound to the lifetime of "self", pretty much like every other child
> of self (including labels, buttons, etc.).
>
> > This code is part of a slot. Whenever this code is hit, a new dialog is
> > created with destroying the old one. I thought, that the garbage

Typo: created without destroying ...

> > collector should take care of deleting the old one.
>
> No, because like any other QObject, its lifetime is bound to its parent,
> *irrespective* of the lifetime of the Python object (which can be destroyed
> and recreated on demand). Think of how many widgets you (probably) create
> to compose a dialog and for which you do *not* keep a Python reference.

In the meantime I did some more tests. I changed the QDialog derived dialog to 
a QWidget derived one and now it get deleted by the garbage collector, when I 
create a new instance. It seems, that the C++ QDialog gets detached from its 
Python proxy.

>
> > Same thing happens with nonmodal dialogs spawned from the QMainWidget.
>
> When
>
> > closing the application, I have to close every single dialog, that was
> > displayed via the show() method, individually.
>
> The point is that PyQt *specifically* implements a workaround for QDialog
> and QPopupMenu when used as *modal* dialogs. If you run the exec_loop()
> method (and thus request modal behaviour), their lifetime semantic is
> explicitally changed and becomes bound to the *Python* reference. This
> allows to write Python code to use modal dialogs which works
> "out-of-the-box".
>
> For modeless dialogs, you're out of luck. There are at least a couple of
> ways to do what you want:
>
> * Explicitally delete the widget before constructing the new one. There is
> no equivalent of "delete dlg" in Python, so the common way is to call the
> deleteLater() method. This is usually enough. Notice that you can force the
> deleteLater() message to be immediately processed by doing:
> qApp.sendPostedEvents(widget, QEvent.DeferredDelete). Usually you don't
> need this, though, and waiting till the next event loop is good enough.

It worked ok in PyQt3 but shows the weird (at least for me) behavior for 
PyQt4. Therefore I suspect something wrong with PyQt4 and QDialog.

>
> * Tell SIP that you want the lifetime of the dialog to be bound to the
> Python object. This is spelled: "sip.transferback(self.dlg)". You need to
> import sip, of course. This is *exactly* what PyQt does when you call the
> exec_loop() method in QDialog and QPopupMenu.
>
> > Additionally I have seen this strange behavior. If I create the dialog
>
> above
>
> > with self as a parent, the dialog containing the slot is put behind all
> > other windows.
> >
> > Another observation is, that the newly generated dialog (using the above
> > code) is put centered on top of the generating dialog. I expected the
>
> window
>
> > manager to take care of the placement.
> >
> > The last observation is, that the generating dialog is always behind the
> > generated dialog. I cannot bring it into the foreground.
>
> I see these behaviours with Qt under Windows, but I didn't bother
> investigated, and I blamed it on Windows' window manager. I don't think
> PyQt has anything to do with either, though. Maybe there is a workaround
> for the latter you mentioned (in the WFlags) but I don't recall.

Detlev
-- 
Detlev Offenbach
detlev at die-offenbachs.de




More information about the PyQt mailing list