Correct method to launch a PyQt/PySide widget from the shelf

   14430   5   4
User Avatar
Member
53 posts
Joined: June 2009
Offline
Hi!

Now Houdini 14 ships with PySide I would like to translate some of my tools that were developed in PyQt4 for Houdini 13.
But I am a bit lost regarding how to do that correctly and how to launch the tools from the Houdini shelf.

In Houdini 13, I used to be able to launch a PyQt GUI from the shelf running this set of command, as explained here http://www.sidefx.com/docs/houdini13.0/hom/cookbook/pyqt/part1/: [sidefx.com]

app = QtGui.QApplication.instance()
if app is None:
app = QtGui.QApplication()
win = WidgetUI()
win.show()
pyqt_houdini.exec_(app, win)


Now, with PySide, the pyqt_houdini module is not needed anymore:
http://www.sidefx.com/docs/houdini14.0/hom/cookbook/qt/ [sidefx.com]

So I find myself trying to move my code from PyQt4 to PySide, and at the same time from H13 to H14

One important difference between PyQt and PySide is the lack of uic.loadUiType() function in PySide
I found two different ways to mimic this command:
https://github.com/fredrikaverpil/pyVFX-boilerplate/blob/master/boilerplate.py [github.com]
https://github.com/lunaryorn/snippets/blob/master/qt4/designer/pyside_dynamic.py [github.com]

I have been trying various combinations of the above with Houdini 14, but I could not find one that works properly

Is there anyone that could shed some light on this problem?
Thank you for your help!

=====
I attach some files as examples:
widgetPyqt.py: using PyQt4, with two different command for H13 and H14: runHoudini13() and runHoudini14()
widgetPyside141.py: using PySide and loadUiType() equivalent found in pyVFX-boilerplate [github.com]
widgetPyside142.py: using PySide and UiLoader() class found in pyside_dynamic.py [github.com]

Here are the results of my tests:

H13.0.665
widgetPyqt.py with the command runHoudini13(): run fine, GUI shows up
widgetPyqt.py with the command runHoudini14(): does not work, the GUI appears briefly and disappear immediately
widgetPyside141.py with the command runHoudini(): does not work, the GUI appears briefly and disappear immediately
widgetPyside142.py with the command runHoudini(): run fine, GUI shows up

H14.0.272
widgetPyqt.py with the command runHoudini13(): GUI launch, but the interface does not respond to mouse clics, I have to force quit the application
widgetPyqt.py with the command runHoudini14(): GUI appears briefly and disappear immediately, then houdini crashes
widgetPyside141.py with the command runHoudini(): does not work, nothing shows up, but houdini does not crash
widgetPyside142.py with the command runHoudini(): GUI shows up, I can launch multiple instance of the GUI, but stylesheet is not correct

In the files I also provide the runStandalone() function so you can test it’s working fine in a separate python environment

Environment:
OSX Yosemite 10.10.2
Houdini 13.0.665 and Houdini 14.0.272
Qt version: 4.8.5
SIP version: 4.15.4
PyQt version: 4.10.3
PySide version: 1.2.2
=====

Attachments:
widget.zip (2.6 KB)

User Avatar
Member
104 posts
Joined: July 2005
Offline
Hello,

I'm currently running into same issues with Houdini 15 and Pyside.

I see no one has replied to post - maybe someone has actually figured out what's going and can shed some light?

The window briefly pops open and closes instantly.

Thanks
User Avatar
Member
79 posts
Joined: April 2011
Offline
http://www.sidefx.com/docs/houdini15.0/hom/cb/qt [sidefx.com]

http://www.sidefx.com/docs/houdini15.0/hom/hou/ui#mainQtWindow [sidefx.com]

Take a look at those two docs….
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
I am having this issue in H16. The window opens properly if I define the class inside the shelf tool's scripting window, but if I try to store it in an external file and then import it as a module into the shelf tool then the window just opens and then closes.

I tried fixing this by parenting the window to the houdini session as shown in the documentation, but then I start getting “RuntimeError: Internal C++ object (PySide.QtGui.QListWidget) already deleted.”.

Unless someone knows a work around, it seems like storing your python windows externally is a no go.


SOLVED:
Rvinluan gives a good workaround in this thread [www.sidefx.com].
Edited by NFX - March 29, 2018 15:40:18
User Avatar
Member
385 posts
Joined: April 2017
Offline
You just have to make sure the window's parent is set to Houdini's main window instance.

from PySide2 import QtGui, QtCore
import hou

def getHoudiniWindow():
	win = hou.ui.mainQtWindow()
	return win

class TestWindow(QtWidgets.QDialog):
	def __init__(self):
		super(TestWindow, self).__init__()
		layout = QtWidgets.QVBoxLayout()
		self.setLayout(layout)
		button = QtWidgets.QPushButton('hi i am a dialog')
		button.clicked.connect(self.close)
		layout.addWidget(button)
		self.setParent(hou.ui.mainQtWindow(), QtCore.Qt.Window)
		self.show()

That self.setParent() line binds the QDialog we're making here to Houdini's Qt mainWindow instance. All you have to do from here is create an instance of this class in your shelf tool:

import test_window
w = test_window.TestWindow()
MOPs (Motion Operators for Houdini): http://www.motionoperators.com [www.motionoperators.com]
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
Despite parenting my window to the Houdini Qt session, in my tests I was still having problems with python deleting my references. Rvinluan's solution of creating an instance of the widget and adding it to the hou.session fixed the problem.
  • Quick Links