Nov 092011

This is a follow up post to my previous one on Installing PyQt4 for Maya 2011

Recently while putting together my next video tutorial for Python for Maya, I came to a section where I wanted to demo PyQt4 in Maya2012. But I was concerned that viewers would have to go through the complicated steps of building PyQt4. I noticed that other people have made available precompiled PyQt installers for windows (here) but I could not find any for OSX or linux. So I decided to put together a build.

I created a new project on github called MyQt4

Its a Makefile for completely downloading and building PyQt4 for maya, and generating a .pkg installer. Hopefully someone can contribute improvements since I dont have a ton of experience writing makefiles, and also that someone might create a linux version.

Here is a link to the latest pkg build:

Snow Leopard: 


Mountain Lion:

Here are builds other people have made:

Mar 182010

“App’ing up” PyQt… ugh.

One of biggest problems with PyQt is distributing it in a stand-alone package. Even worse… wanting to make your Qt plugins still function (Phonon, jpeg, etc). At work I constantly had this battle, along with my co-worker Tory. She actually has a long-standing issue with this, and had to resort to workarounds or half fixes. Here is Tory’s original post regarding the issue .

I would see an error similar to this when trying to package up and run an app using the Phonon module.

WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded



does add things like the jpeg plugin, but never seemed to fix the Phonon issue. I finally decided to randomly look online for a solution, again, last week. What I found was a partial solution, followed by me trying one more thing and bam…it worked! Video playback from my .app standalone package.

Here is what I did …
(btw you might have to modify the location of the plugin, since I happen to be using OSX)

  1. In your file, which is used for py2app, py2exe, or similar… add this to the DATA_FILES list, so that it looks as such:
    DATA_FILES = [('phonon_backend',
    ['/Developer/Applications/Qt/plugins/phonon_backend/libphonon_qt7.dylib'] )]

    This will put the phonon backend plugin into the RESOURCES folder in the app.

  2. Package up your application via py2app / py2exe / etc.
  3. If you are on OSX, use macdeployqt on the app:
    >>> macdeployqt
  4. Go into the app that was created (show package contents if you are on a mac), and move the phonon_backend directory FROM the Resources directory TO the PlugIns directory (which should be at the same level as Resources).

That should be it!

Mar 162010

I get to do a lot of interesting applications at SouthPark. This one in particular was the most challenging use of PyQt that I have experienced to date.

The backstory….
The art department wanted a tool to help them track assigned tasks, the progress, and to share media and notes associated with the tasks. Furthermore, they wanted to be able to skin the interface with custom graphics to make it their own.

During the winter break (about a month) I was able to come up with version 1.0 of TaskMonster. It was written in python, using PyQt for the UI, sqlalchemy to talk to the database, and twisted for the client/server communication. Each client app sends messages to a small server daemon which in turn tells the rest of the clients about the updates.

Version 2.0 Alpha…
Tony Postma, from the art department, put together a design in Corel which I could hopefully implement in the UI.  It called for the users to be represented as little pods in a circle around the supervisor, Adrien Beard. And each user pod could be clicked and rotated into place, in order to view that persons tasks.
After a bunch of testing I was able to design a rotating widget that could dynamically lay out N widgets around it in a circle, track their position, and jump to any other widget. I was also able to break down the corel->illustrator file, into a combination of SVG and PNG images, and skin the UI via CSS stylesheets.
Its currently an alpha release. I guess I need to really learn how to control the widget painting, to make it faster. Never had to do this much before.

What I came up with…        Click here to watch the demo video

Mar 102010

You know when you have all these widgets laid out in your class, and you are hooking up all the connections, and you say “Aw dammit I have to subclass QLabel now just so make it ignore blahEvent”? You end up with all these little widget subclasses, where all they are doing is ignoring an event.

I noticed I was doing this a few times, in more than one of my classes, and finally got annoyed for the last time. I figured there had to be a simple way of just overloading the method on the normal object when I create an instance. Fortunately python considers everything objects and pretty much anything can be changed. So I did this:

myLabel = QLabel()
myLabel.mousePressEvent = lambda event: event.ignore()


I have also had to make clickable widgets, such as QLabel:

myLabel = QLabel()
myLabel.mousePressEvent = lambda event: myLabel.emit(SIGNAL("clicked"))

Or if you had to do more than just a single statement:

myLabel = QLabel()
def clickedEvent(event):
    # do other stuff
        # do stuff
myLabel.mousePressEvent = clickedEvent

I like this better than piling up subclasses that don’t do much.