PySide: More ScriptJobs

Previously I showed how to add a ScriptJob to a PySide QDialog. This time I’m going to extend that concept. We’re going to make a window that has a combo menu which dynamically loads QWidgets, one of which creates a ScriptJob. That’s the basic functionality, but there is one added twist. We need to kill the job when the combo menu changes the QWidget or when the window is closed.

Let’s start with the MainWindow class. In the __init__ we add the variable self.SCRIPT_JOB_NUMBER. This is used to store any ScriptJob created by the dynamic widgets.

Now the window’s UI.

Most of this is straight forward. The two items of note are self.comboMenu and self.dynamicLayout. The combo menu triggers the updateGui() method. This method is what sets the widgets for self.dynamicLayout.

Let’s break down updateGui().

The first thing we do is get the active item in self.comboMenu.

Next we want to clear out self.dynamicLayout. We do this with the method clearLayout() (more on this later).

Here I build a dictionary. The dicts keys correspond to the indexes of the combo menu, while the values are custom QWidget classes. I then use currentComboIndex to get the correct widget class and then add it to self.dynamicLayout.

The QWidget class at index 0 of the combo menu is the only one with a ScriptJob. If that is the active widget then we grab it’s ScriptJob number and assign it to self.SCRIPT_JOB_NUMBER in MainWindow().

We’re almost done with MainWindow(). All that’s left is to add the method closeEvent(), which I cover in the previous example. Basically this guy is needed to kill the ScriptJob when the user closes the window. Otherwise it’ll hang around till Maya is shutdown and to many of these things active can cause problems.

Before we put it all together I need to go back and address clearLayout(). This is used to remove all the items from a PySide layout. Without this we would end up with an ever growing window. Each change of the combo menu would add a new QWidget instead of replacing the existing one. So clearLayout() loops through all the items in a layout and deletes them.

Okay, so that’s the entire MainWindow class. And here it is put together.

Now we need to make WidgetOne and WidgetTwo. These are the custom QWidget classes used in updateGui().

To keep things simple I’m using the same ScriptJob from my previous example – the user selects an item and a label on the window updates to show the item’s name.

We’ll start with WidgetOne. This time we are extending QWidget instead of QDialog since these guys will be widgets added to a layout and not windows in their own right.

For the layout we have two QLabels. The first, self.widgetLabel, displays the name of the active widget. This way you can actually see the widgets changing when the combo menu changes. The second, self.selectedLabel, is the one changed by the ScriptJob.

The ScriptJob is then created, but we need to handle this in a special way. A ScriptJob can have a parent assigned at creation. This allows the job to be automatically killed if the parent is destroyed. We want this to happen because of the dynamic nature of the widgets and because we don’t need the job when it’s widget is inactive. The catch her is that a ScriptJob can’t have a PySide object for a parent. So in order to make this work we create a Maya UI object, assign it as the parent for the ScriptJob, and then convert the Maya UI object into a PySide object. Now we can take this newly created PySide object and add it to the widget’s layout.

The last thing to add to WidgetOne is the class method that the ScriptJob triggers.

Here is the full version of WidgetOne.

WidgetTwo is just a deeply watered down version of WidgetOne. All it has is a single QLabel with it’s name.

And finally here is everything put together.