PySide: Using ScriptJobs
ScriptJobs are something I use from time-to-time and I thought I would show a couple examples of how I use them with PySide interfaces.
First up, a single UI window that creates a ScriptJob and then deletes it upon closing. The ScriptJob in this case sets the text of a QLabel to the name of the selected object. Here is the basic window that extends QDialog.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import maya.OpenMayaUI as omui from PySide import QtCore from PySide import QtGui from shiboken import wrapInstance import traceback import maya.cmds as cmds def maya_main_window(): ''' Return the Maya main window as a Python object ''' main_window_ptr = omui.MQtUtil.mainWindow() return wrapInstance( long( main_window_ptr ), QtGui.QWidget ) class MainWindow( QtGui.QDialog ): def __init__( self, parent=maya_main_window() ): super( MainWindow, self ).__init__( parent ) self.winName = 'My Main Window' self.userInput = None self.create() def create( self ): # Check to see if this UI is already open. If it is then delete it before # creating it anew. if cmds.window( self.winName, exists=True ): cmds.deleteUI( self.winName ) # Set the window object name and window title. self.setObjectName( self.winName ) self.setWindowTitle( self.winName ) # Build the UI. layout = QtGui.QVBoxLayout( self ) self.selectedLabel = QtGui.QLabel() self.selectedLabel.setText( 'Nothing Selected' ) layout.addWidget( self.selectedLabel ) ''' RUN THE WINDOW ''' testUI = MainWindow() testUI.show() |
Now lets add the ScriptJob. In the create method of MainWindow we add the following lines.
1 2 |
# Create the script job and store it's number. self.SCRIPT_JOB_NUMBER = cmds.scriptJob( event=[ 'SelectionChanged', self.onSelectionChange ], protected=True ) |
When a ScriptJob is first created it returns the job number, which we use later on to delete the job when the window is closed. We’ll add self.onSelectionChange in a second. For now all you need to know is it’s the class method that changes the window’s QLabel text.
Next we extend QDialog’s closeEvent method by adding a line that kills our ScriptJob before closing the window.
1 2 3 4 |
def closeEvent( self, event ): # Clean up the script job stuff prior to closing the dialog. cmds.scriptJob( kill=self.SCRIPT_JOB_NUMBER, force=True ) super( MainWindow, self ).closeEvent( event ) |
And finally, to the MainWindow class we add the method onSelectionChange. This grabs the currently selected objects. If there is only one then it changes the window’s QLabel text to the name of the object.
1 2 3 4 5 6 7 8 9 10 11 |
def onSelectionChange( self ): # Change the text for the label. selList = cmds.ls( selection=1, long=True ) if len( selList ) == 1: shortName = selList[0].split( '|' ) selName = shortName[ len(shortName)-1 ] self.selectedLabel.setText( selName ) elif len( selList ) > 1: self.selectedLabel.setText( 'Select One Object' ) else: self.selectedLabel.setText( 'Nothing Selected' ) |
Put all of that together and we have this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import maya.OpenMayaUI as omui from PySide import QtCore from PySide import QtGui from shiboken import wrapInstance import traceback import maya.cmds as cmds def maya_main_window(): ''' Return the Maya main window as a Python object ''' main_window_ptr = omui.MQtUtil.mainWindow() return wrapInstance( long( main_window_ptr ), QtGui.QWidget ) class MainWindow( QtGui.QDialog ): def __init__( self, parent=maya_main_window() ): super( MainWindow, self ).__init__( parent ) self.winName = 'My Main Window' self.userInput = None self.create() def create( self ): # Check to see if this UI is already open. If it is then delete it before # creating it anew. if cmds.window( self.winName, exists=True ): cmds.deleteUI( self.winName ) # Set the window object name and window title. self.setObjectName( self.winName ) self.setWindowTitle( self.winName ) # Build the UI. layout = QtGui.QVBoxLayout( self ) self.selectedLabel = QtGui.QLabel() self.selectedLabel.setText( 'Nothing Selected' ) layout.addWidget( self.selectedLabel ) # Create the script job and store it's number. self.SCRIPT_JOB_NUMBER = cmds.scriptJob( event=[ 'SelectionChanged', self.onSelectionChange ], protected=True ) def closeEvent( self, event ): # Clean up the script job stuff prior to closing the dialog. cmds.scriptJob( kill=self.SCRIPT_JOB_NUMBER, force=True ) super( MainWindow, self ).closeEvent( event ) def onSelectionChange( self ): # Change the text for the label. selList = cmds.ls( selection=1, long=True ) if len( selList ) == 1: shortName = selList[0].split( '|' ) selName = shortName[ len(shortName)-1 ] self.selectedLabel.setText( selName ) elif len( selList ) > 1: self.selectedLabel.setText( 'Select One Object' ) else: self.selectedLabel.setText( 'Nothing Selected' ) ''' RUN THE WINDOW ''' testUI = MainWindow() testUI.show() |
That’s it! We now have a PySide QDialog that creates a ScriptJob when it’s opened and then kills the job before it closes.
Sometimes it can be useful to list all the active ScriptJobs running in Maya. To do this run the following in the Script Editor.
1 2 3 4 5 |
import maya.cmds as cmds jobs = cmds.scriptJob( listJobs=True ) for job in jobs: print job |
In the next post I’ll show how I handle ScriptJobs that are created/killed by a dynamically loaded QWidget within a QLayout.