[PyKDE] Issue with QDialog and lifetime

Giovanni Bajo rasky at develer.com
Wed Jul 6 17:44:45 BST 2005


Phil Thompson <phil at riverbankcomputing.co.uk> wrote:

>>>>> Does anyone see a potential problem with exec_loop() transferring
>>>>> ownership of the dialog instance back to Python?
>>>>
>>>> Well, which C++ API would you intend to call to achieve this? We still
>>>> need the QDialog to keep its parent widget because it is the widget on
>>>> which the dialog is modal.
>>>
>>> [...]
>>> You should be able to test this with sip.transfer( dlg, 0 ) just
>>> before dlg.exec_loop().  Ultimately, a sipTransfer() should be added
>>> to the %MethodCode for exec_loop().
>>
>> Yeah this works very well!
>> Phil, what do you think of this? It solves a nasty problem.
>
> Could somebody summarise the original problem for me, and why this is
> required?

The problem is that the idiomatic way of using modal dialogs in C++ is to
create local variables, which gets destroyed when their scope finishes (when
the function exits). Moreover, the dialogs have to be children of whatever
widgets they are modal over (e.g. the main window).

This has no direct translations in PyQt. If you do:

def slotWhatever(self):
   dlg = MyModalDialog(self)
   if dlg.exec_loop() == QDialog.Accepted:
       return dlg.data()
   return None

you are leaking "dlg" because its lifetime is bound to its parent. The
current common workaround is something like:

def slotWhatever(self):
   dlg = MyModalDialog(self)
   try:
       if dlg.exec_loop() == QDialog.Accepted:
           return dlg.data()
       return None
   finally:
       dlg.deleteLater()

which is ugly and error-prone (you have to remember to do it).

James proposed this solution:

def slotWhatever(self):
   dlg = MyModalDialog(self)
   sip.transfer(dlg, 0)
   if dlg.exec_loop() == QDialog.Accepted:
       return dlg.data()
   return None

and then proposed to hardcode the transfer() call within the %MethodCode for
QDialog.exec_loop. I'll remember you that exec_loop is called only for modal
dialogs, while for modeless dialogs show() is called.
-- 
Giovanni Bajo




More information about the PyQt mailing list