Threading in Maya2011 and PyQt
So I might have been a bit too eager yesterday. Threading does work, just not the way I was trying to do it.
I tried doing something a little fancier this morning, actually creating something. So I had this code in the run() method of the QThread subclass:
cmds.ls() time.sleep(1) cmds.sphere() time.sleep(1) cmds.cylinder() time.sleep(1) cmds.ls()
This works, BUT: it seems to break Maya a bit. The viewport refuses to update by itself after this, selecting stuff does not show up highlighted until I tumble, same for the translate handle, which does not show up by simply pressing the W-key.
It turns out, that calling the Maya commands from the main thread is still the proper way to go, BUT, being able to use Qt’s signals, makes things nice and easy. Here’s the code I ended up using:
from PyQt4 import QtCore, QtGui
class TestThread(QtCore.QThread):
def run(self):
import maya.cmds as cmds
import time
self.emit(QtCore.SIGNAL("range"), 0, 4)
time.sleep(1)
self.emit(QtCore.SIGNAL("list"))
self.emit(QtCore.SIGNAL("inc"))
time.sleep(1)
self.emit(QtCore.SIGNAL("sphere"))
self.emit(QtCore.SIGNAL("inc"))
time.sleep(1)
self.emit(QtCore.SIGNAL("cylinder"))
self.emit(QtCore.SIGNAL("inc"))
time.sleep(1)
self.emit(QtCore.SIGNAL("list"))
self.emit(QtCore.SIGNAL("inc"))
class MyFrame(QtGui.QFrame):
def __init__(self):
QtGui.QFrame.__init__(self)
self.setWindowTitle("Test")
self.t = TestThread()
button = QtGui.QPushButton("Start", self)
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(button)
self.pbar = QtGui.QProgressBar(self)
self.layout().addWidget(self.pbar)
self.pbar.reset()
self.connect(button, QtCore.SIGNAL("clicked()"), self.t.start)
self.connect(self.t, QtCore.SIGNAL("list"), self.doList)
self.connect(self.t, QtCore.SIGNAL("sphere"), self.makeSphere)
self.connect(self.t, QtCore.SIGNAL("cylinder"), self.makeCylinder)
self.connect(self.t, QtCore.SIGNAL("range"), self.setPBarRange)
self.connect(self.t, QtCore.SIGNAL("inc"), self.incPBar)
def doList(self):
print cmds.ls()
def makeSphere(self):
cmds.sphere()
def makeCylinder(self):
cmds.cylinder()
def setPBarRange(self, minimum, maximum):
self.pbar.setRange(minimum, maximum)
self.pbar.setValue(0)
def incPBar(self):
self.pbar.setValue(self.pbar.value() + 1)
frame = MyFrame()
frame.show()
Now, hitting the “Start” button starts the thread, which after every second sends a signal to the QFrame subclass living in the main thread, which in turn fires off the Maya commands.