Threading in Maya2011 and PyQt

April 8th, 2010

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.

in 3D, Maya, Python

Leave a Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Spam protection by WP Captcha-Free