I am trying to write a python window that launches when a shelf tool button is pressed. I have been able to launch the window, however it seems that all the references to my widgets break once the window is initialized. Callbacks and anything that happens afterwards result in a “RuntimeError: Internal C++ object (PySide.QtGui.QListWidget) already deleted.” I'm guessing that this has something to do with Houdini's event loop?
I will try to post some example code tomorrow, but I just wanted to post this and see if anyone had any ideas.
Problem with Custom Shelf Tool Python Window
7040 5 4- NFX
- Member
- 183 posts
- Joined: Dec. 2011
- Offline
- NFX
- Member
- 183 posts
- Joined: Dec. 2011
- Offline
So here is the sample code I promised. After further testing it, the problem definitely has to do with parenting the window to Houdini's mainQtWindow. The .ui file that the code is reading in is just a button and a qlineedit inside a horizontal layout. This script is being run via a shelf tool.
Just to reiterate, if I click the button on this example I get aerror. Which seems odd since the whole point of parenting the window to Houdini is to avoid references being deleted.
If I get rid of theline then it runs, but only if the class is defined inside the tool's script window. If I move the class into an external file and then load it as a module, then the window is deleted as soon as it's made. My guess is that this is due to its references being cleaned up since it is not parented to Houdini's Qt session.
Is there a way to work around this?
import os from PySide import QtCore from PySide import QtGui from PySide import QtUiTools class TweakedDemo(QtGui.QWidget): def __init__(self, parent=None): super(TweakedDemo, self).__init__(parent) loader = QtUiTools.QUiLoader() gui_path = os.path.join(os.getenv('HIP'),'testGui.ui') self.gui = loader.load(gui_path) self.setGeometry(500, 300, 250, 110) self.setWindowTitle('Tweaked Demo') button = self.gui.findChild(QtGui.QPushButton, "button") self.field = self.gui.findChild(QtGui.QLineEdit, "textField") self.connect(button, QtCore.SIGNAL('clicked()'), self.changeText) vbox = QtGui.QVBoxLayout() vbox.addWidget(self.gui) self.setLayout(vbox) def changeText(self): self.field.setText('Hello World') def closeEvent(self, event): self.setParent(None) dialog = TweakedDemo() dialog.setParent(hou.ui.mainQtWindow(), QtCore.Qt.Window) dialog.show()
Just to reiterate, if I click the button on this example I get a
RuntimeError: Internal C++ object (PySide.QtGui.QListWidget) already deleted.
If I get rid of the
dialog.setParent(hou.ui.mainQtWindow(), QtCore.Qt.Window)
Is there a way to work around this?
Edited by NFX - March 29, 2018 13:44:40
- rvinluan
- Staff
- 1255 posts
- Joined: July 2005
- Offline
Hello,
I think I have run into this issue before. It has to do with the lifespan of Python variables and PySide/shiboken deciding what it owns and what it can delete. It's a long explanation but here are a couple of workarounds you can try.
1) Assign the result of
2) Alternatively, don't parent to the main window. Instead assign your dialog to a variable that lives past the lifetime of the shelf tool's Python context. For example:
I hope this helps.
Cheers,
Rob
I think I have run into this issue before. It has to do with the lifespan of Python variables and PySide/shiboken deciding what it owns and what it can delete. It's a long explanation but here are a couple of workarounds you can try.
1) Assign the result of
hou.ui.mainQtWindow()
to a variable that lives past the lifetime of the shelf tool's Python context. For example:hou.session.mainWindow = hou.ui.mainQtWindow() dialog.setParent(hou.session.mainWindow, QtCore.Qt.Windows)
2) Alternatively, don't parent to the main window. Instead assign your dialog to a variable that lives past the lifetime of the shelf tool's Python context. For example:
hou.session.dialog = dialog
I hope this helps.
Cheers,
Rob
- NFX
- Member
- 183 posts
- Joined: Dec. 2011
- Offline
- andehpandeh
- Member
- 20 posts
- Joined: March 2019
- Offline
- toadstorm
- Member
- 359 posts
- Joined: April 2017
- Offline
It has to do with garbage collection in Python. If you create an instance of an object but there's nothing in the main loop that's actually referencing that instance, Python will automatically purge it from memory. The moment you either connect the window to something permanent like the MainWindow, or store it in a persistent object like hou.session, Python recognizes that something else in the event loop is storing a pointer of sorts to this new window, and so it won't be removed.
MOPs (Motion Operators for Houdini): http://www.motionoperators.com [www.motionoperators.com]
-
- Quick Links