Executing code on close of a docked PySide QDialog

1,215 views
Skip to first unread message

AK Eric

unread,
Jan 23, 2015, 2:23:19 PM1/23/15
to python_in...@googlegroups.com
I've authored a window in PySide (via QDialog), and recently made it dockable by inheriting from maya.app.general.mayaMixin.MayaQWidgetDockableMixin  (in 2015).  Surprisingly easy.

In the QDialog's closeEvent method, I do a bit of cleaning up of API callbacks. What I've found is:  If the window is floating and not docked, the closeEvent code executes.  But if the window is docked and closed (via the [x] in the corner), the closeEvent doesn't execute.

Any thoughts on what I need to do to track this close state?  Or possibly another method to use when closing the docked window?

thanks

Marcus Ottosson

unread,
Jan 23, 2015, 2:33:25 PM1/23/15
to python_in...@googlegroups.com
It's possible that "closing" a docked window isn't the same as physically closing it via the X button on the Window; the latter potentially signalling via the Window Manager of the OS whereas the former is internal to Qt (i.e. deleting a widget).

This might be related.

In which case it might be a parenting matter and you'll need to pass the DeleteOnClose bit.

Timm Wagener

unread,
Jan 23, 2015, 2:59:27 PM1/23/15
to python_in...@googlegroups.com
Hi Eric,

i have done the same thing a few times now (Parenting widgets under inherited dockwidgets if the user wants them dockable and needing to clean up stuff (QTimer etc.) ).

Maybe the reason that your closeEvent is not called when docked is, that you are actually closing the DockWidget and not your QDialog and therefore you are triggering the Dockwidgets closeEvent.
What you could do in this case would be to override the DockWidgets closeEvent, and from in there 
1. Also clean up or
2. call the child QDialog closeEvent that cleans up.

Also, you could override the instance factory method (__new__) of your subclassed QDialog and search for instances of your custom QDialog type and if some are found,
schedule them for deletion via deleteLater(). This way, you would make sure that, before new instance creation, all old instances with timers etc. are cleaned.

I often have a clean_up() method called within closeEvents and a cleanup/deletion in __new__.

And it might be personal preference, but i would usually prefer to inherit from default Qt types, such as QDockWidget instead of specialized Maya types like maya.app.general.mayaMixin.MayaQWidgetDockableMixin if they basically do the same......but maybe that just personal.

Cheers,
Timm

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOACrhoQZF0KkbAD3mtoKbrV0-T4cjK%2BYCr9fDdxx_mY-w%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--
Timm Wagener
Technical Artist / 3D Generalist

www.timmwagener.com

Email:
wagen...@gmail.com

Phone:
0178-2810920


Marcus Ottosson

unread,
Jan 23, 2015, 4:16:45 PM1/23/15
to python_in...@googlegroups.com
When things are properly parented, is there really a need for clean-up? Wouldn't dialogs and timers get picked up and thrown out during garbage collection?

--
Marcus Ottosson
konstr...@gmail.com


Timm Wagener

unread,
Jan 23, 2015, 4:33:15 PM1/23/15
to python_in...@googlegroups.com
I think the issue is that a closeEvent hides the widgets instead of deleting them by default. But it seems that this behaviour can be changed.
To make a widget delete itself when it’s closed, use the Qt::WA_DeleteOnClose widget attribute.

This might be the best solution, never tried it though.
As soon as a deletion has been scheduled (with deleteLater() or probably Qt::WA_DeleteOnClose) and it happend, i guess the gc will do its job.
Anybody please correct me if i'm telling nonsense ;)

Cheers,
Timm

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

AK Eric

unread,
Jan 23, 2015, 4:55:05 PM1/23/15
to python_in...@googlegroups.com
Timm: This is how my inheritance looks:

class App(MayaQWidgetDockableMixin, QDialog):

So I am overriding the closeEvent in that class with my cleanup code, but like mentioned, it's not being called when docked.  Also:  "closeEvent hides the widgets instead of deleting them by default" : That's what I've experienced as well:  I am using the WA_DeleteOnClose for that class:  Without it, it seems the closeEvent isn't called when closed in window form.  But in docked mode, nada.

Marcus:  I have all my windows (to my knowledge) properly parented.  But "closing" them doesn't seem to actually delete them (see comment above) without the WA_DeleteOnClose option.

So what I need is a way to "delete" my QDialog correctly when it's docked.  Currently, when docked, when I hit the [x] it just seems to "hide" it.  It appears that it was deleted (since it vanishes from the scene, but in fact it's still there, just not drawing?


AK Eric

unread,
Jan 23, 2015, 5:00:02 PM1/23/15
to python_in...@googlegroups.com
Tracked it down:  The MayaQWidgetDockableMixin class has a  dockCloseEventTriggered method:  I can call to my cleanup code in there, and all is happy now.

Thanks for the help!

Justin Israel

unread,
Jan 23, 2015, 8:26:00 PM1/23/15
to python_in...@googlegroups.com
Normally when you are only using the Qt QDockWidget you can just work with the closeEvent on the QDockWidget, and do whatever you want to manage the widget it is managing. I had never seen these Maya-provided mixins until now, but looking at the source for it, I can see they do all the custom wiring under the hood, and exposed, like you said, that custom hook for you to implement to receive the close event. 

@Timm, regarding the garbage collection. There are two levels of cleanup that would happen here. The deleteLater() is part of the Qt cleanup, where the C++ instance would get deleted, but that could happen independently of the python garbage collection. It is possible to hang onto a python object beyond the point where the C++ pointer has been deleted, and conversely to let a python reference fall out of scope but leak the C++ pointer because the parent-child relationship still keeps it alive. That can happen when you parent things to the maya main window, and then at some point you close your window and let your reference go, thinking it is deleted. But really the instance is still alive and hidden. 

We had some discussions about this in previous threads. Just for reference here are some links I gave in the past:

# Leaking resources in Maya because of the Qt parent/child relationship

# A helper for seeing if you are leaking objects or watching the growth of certain types






On Sat Jan 24 2015 at 11:00:04 AM AK Eric <war...@sbcglobal.net> wrote:
Tracked it down:  The MayaQWidgetDockableMixin class has a  dockCloseEventTriggered method:  I can call to my cleanup code in there, and all is happy now.

Thanks for the help!

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Timm Wagener

unread,
Jan 24, 2015, 11:40:01 AM1/24/15
to python_in...@googlegroups.com
Thanks for the examples Justin!

@AKEric: I never had heard about MayaQWidgetDockableMixin too :) Always do the docking via a dock_it() method in the __init__, so not using multiple inheritance. But if it works for you, then its totally fine ;)

Cheers,
Timm


For more options, visit https://groups.google.com/d/optout.

AK Eric

unread,
Jan 24, 2015, 3:01:47 PM1/24/15
to python_in...@googlegroups.com
I've been making maya ui's forevers (via mel at first and now python), but never really messed with docking.  This is really my first attempt at doing PySide, and docking PySide, so I have on doubt that maybe some part of my setup is wrong ;)  
Reply all
Reply to author
Forward
0 new messages