# Custom Python QDialog crash

**URL:** <https://discourse.slicer.org/t/custom-python-qdialog-crash/9899>\
**Category:** Development\
**Tags:** python, qt\
**Created:** [January 21, 2020, 8:22pm UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899 "2020-01-21T20:22:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Johan\_Andruejol](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/johan_andruejol/32/3639_2.png) [@Johan\_Andruejol](https://discourse.slicer.org/u/Johan_Andruejol)\
**Post date:** [January 21, 2020, 8:22pm UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899/1 "2020-01-21T20:22:08Z")

</div>

Hi everyone !

I am trying to create a custom QDialog in Python. Whenever you add a custom signal/slot connection, the application crashes on exit.

Here is the minimal example you can reproduce the crash with, following the steps:

- Open Slicer
- Run the python code below:

> ```
> class CustomDialog(qt.QDialog):
> def __init__ (self, parent = None):
> qt.QDialog. __init__ (self, parent)
> self.connect('accepted()', self.myCustomSlot)
> def myCustomSlot(self):
> print("Doesn't matter")
> 
> w = CustomDialog()
> w.open()
> 
> ```

- Exit Slicer  
 → **CRASH** ☹

Has someone else encountered something like this ? I managed to reproduce it in the nightly and in an older windows build (2019-08-20 hash: 499d10b035181586489f5e3d60ff486a136a12bb).

Thanks !

P.S.: Here is an example of the call-stack after the crash:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/7/2/72277666d7953d90b3b34e6d8a668dd964833154.png)

---

<div class="post-metadata">

**Author:** ![jamesobutler](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jamesobutler/32/7511_2.png) [@jamesobutler](https://discourse.slicer.org/u/jamesobutler)\
**Post date:** [January 21, 2020, 8:39pm UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899/2 "2020-01-21T20:39:36Z")

</div>

I’m currently unable to replicate the crash using today’s Slicer nightly (28737) built by the factory machine on Windows 10.

```auto
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: class CustomDialog(qt.QDialog):
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: def __init__ (self, parent = None):
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: qt.QDialog. __init__ (self, parent)
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: self.connect('accepted()', self.myCustomSlot)
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: def myCustomSlot(self):
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: print("Doesn't matter")
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: w = CustomDialog()
[DEBUG][Qt] 21.01.2020 15:37:22 [] (unknown:0) - Python console user input: w.open()
[DEBUG][Qt] 21.01.2020 15:37:34 [] (unknown:0) - Python console user input: w.accept()
[INFO][Stream] 21.01.2020 15:37:34 [] (unknown:0) - Doesn't matter
[DEBUG][Qt] 21.01.2020 15:38:17 [] (unknown:0) - Python console user input: slicer.app.repositoryRevision
[INFO][Stream] 21.01.2020 15:38:17 [] (unknown:0) - '28737'

```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [January 22, 2020, 12:55am UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899/3 "2020-01-22T00:55:02Z")

</div>

You need to disconnect all signals and delete all widget instances before application shutdown (while the widget that you created in the above example is kept alive forever by the global Python variable).

The [module widget’s cleanup method](https://github.com/Slicer/Slicer/blob/4db181a73e03b3a2c8044ffd4e4174d873b267c3/Base/Python/slicer/ScriptedLoadableModule.py#L99-L106) is added exactly for performing this kind of cleanup.

---

<div class="post-metadata">

**Author:** ![Johan\_Andruejol](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/johan_andruejol/32/3639_2.png) [@Johan\_Andruejol](https://discourse.slicer.org/u/Johan_Andruejol)\
**Post date:** [January 22, 2020, 8:13pm UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899/4 "2020-01-22T20:13:26Z")

</div>

Following your suggestion, I realized that my mistake came from having the QDialog un-parented. Here is what I ended up doing:

```
class CustomDialog(qt.QDialog):
    def __init__ (self, parent = None):
        qt.QDialog. __init__ (self, parent)
        self.connect('accepted()', self.myCustomSlot)
    def myCustomSlot(self):
        pass

w = CustomDialog(slicer.util.mainWindow()) # Parent could be your module GUI
w.show()

```

No more crash, the dialog is properly deleted when the application exits, also no need to worry about the dialog life-cycle.

Thanks a lot for your help !

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [January 22, 2020, 8:37pm UTC](https://discourse.slicer.org/t/custom-python-qdialog-crash/9899/5 "2020-01-22T20:37:18Z")

</div>

Parent widget deletes all child widgets in its destructor. Probably that’s why you don’t need to delete your widget manually when you set the main window as parent.
