Using PySide in Maya 2016 and 2017

Using PyQt Standalone & in Maya


I started learning PySide and PyQt through Maya. However it wasn't until a few years when I figured out how Maya actually worked with PyQt and PySide.

You see, from Maya 2012 and onwards, the entire Maya UI is rebuilt using PyQt. Now-a-days Maya ships with PySide library allowing you to write your custom tools and widgets while in the software. This blog assumes you are aware of Python and Object Oriented Programming concepts, if not please let me know and I can post more blogs about it.

From personal experience, its extremely important to clear ones basics about a topic or else we start adopting bad practices just because they have "worked" so far.

So let's straight jump in.

Most Important Concepts of PyQt/PySide(in my opinion)

  • QObject is the base class for all widgets in Qt.
  • All events run under and an event Loop
  • QObject is called with *args and a parent which can be None. That means:
  • By design Qt widget either 
    • Needs a parent QObject or 
    • Needs to be started after QApplication starts.
This is what a standard __init__() function of a QWidget looks like:


Here QDialog is just another type QObject. Class MyWidget inherits this QDialog, so it will have all the methods of a QDialog and all other classes QDialog inherits from like show(), hide().

Here by default the parent is set as None as this application can either be standalone or run in conjunction with a parent app. In the following blog I will discuss about using parent flag for Maya tools.

Running an Qt application standalone

The next few points explain what actually happens when a Qt application runs
  • A Qt based program runs on events. 
  • An event is anything which can change the behavior of a program(either user interaction or program interaction).
  • These events are fed into an event queue for processing.
  • Then these events are processed by an event loop which runs as long as the program is running.
A QApplication starts an Event loop for any QDialogs or QWidgets which need to run. That code looks something like this:

Here as you can see, we first initialize a QApplication, then we initialize a MyWidget object, show it then run "sys.exit(app.exec_())". The last line implies the program should exit when the application execution terminates. This creates a modal dialog which I will discuss in future blogs.

Running an Qt application in Maya

As I mentioned earlier, all UIs in Maya versions 2012< were rebuilt using Qt. However, they used C++ classes and since this post if about PyQt or PySide, we are not going to go there using C++.

Since Maya is already written in Qt, any time Maya starts, it also starts an event loop, that means there is no need to start a separate QApplication. However it is good practice to still keep all the widgets created in Maya as a child of Maya itself. especially if you plan to have your widgets dockable.

So next question is: How to get the parent object? What would be the parent object? Well, its actually pretty simple: it's Maya's main window.

Now since Maya 2016 comes with PySide preloaded I am going to use a PySide example.

First step is to get Maya's main window as a PySide object. Maya is written in C++ Qt so we first of all need to wrap that C++ Qt object into a Python Qt Object. Then we can pass on that Qt Object as the parent parameter when we initialize the QDialog. This is what the code for that looks like.


Over here as you can see, we use maya's OpenMayaUI library to query mainWindow which returns us the pointer to the main window. "long(ptr)" converts the QWidget pointer into an address which "shiboken.wrapInstance" wraps into a QObject. This QObject is then passed as a parent to the desired QDialog we need to run.


Comments

Popular posts from this blog