Monday, October 3, 2011

Hello, World

 Everyone's favorite topic...Hello, World.

So cliche, and yet, an obviously good starting point.

This tutorial will get you into the Qt world by having you create a very simple QApplication.




Prerequisites

So - to make sure we're all on the same page before continuing.  To work with these tutorials, you will need the following pre-requisites:

  1. Python (any version will do as long as it is compatible with the following...)
  2. Qt
  3. PyQt
If you are on Windows - you will need to install all three, as Python does not come standard.  Provided on the initial post are links to each requirement, and its pretty easy to get builds going for them, so I'm not going to cover that here - there's plenty to google on that topic.

Reading the Examples

Generally, the way we'll approach these tutorials is that I'll show each example in its (relative) entirety - and then break down the code into its parts afterwards.

If you see a code snippet that begins with:

#!/usr/bin/python [filename]


Thats showing that the code within that text block is a full file, saved to the given location.  (If you're from windows, the '~' symbol is just the path to the home directory...think of it as 'c:')

If you see a code snippet that begins with:

>>>


Thats showing that the code within that text block is being run in a command-line interpreter, and being processed line-by-line.

Otherwise, its just a chunk of code taken out of context.

Creating the Hello, World Application

So, to start with, we're going to just make the simplest of applications.  Something that will start up, and popup a message box and exit.

#!/usr/bin/python ~/workspace/pyqt/helloworld/main.py

from PyQt4 import QtGui

if ( __name__ == '__main__' ):
    # create a new application
    app = QtGui.QApplication([])

    # popup a new dialog
    QtGui.QMessageBox.information( None, 'Hello', 'Hello, World!' )

Pretty simple right?

To run your application - depending on your environment and where you saved the file - you should be able to just open a command shell and type:

$ python ~/workspace/pyqt/helloworld/main.py

Again, if you're in windows, it would look more like:

c:> python c:/workspace/pyqt/helloworld/main.py

The Main Scope
While there wasn't a lot of lines of code to type here, there is actually quite a bit that you may or may not be aware of going on underneath the hood.

The import line should be self-explanatory, so we'll skip it.

In the next line, we're checking to make sure that the script has been run within the '__main__' scope.

if ( __name__ == '__main__' ):

The __name__ attribute will always refer to the module scope that you're code is running in.  When a script is imported, the __name__ will be the name that it is imported as, when a script is executed the __name__ value will be __main__, designating that its being run.

You can separate out the code that you want to have available for import and from execution by checking this parameter.

You could have easily written the code without that check, and your script would have worked just as well - however this is bad practice.  Any application logic should always go in the main scope - even if your tool isn't intended to ever be imported.  Otherwise, it would create and run your application on import, which is not the intention.

Application Instances

The next line of code is actually a crucial part of every GUI application written in Qt: the initialization of your application.

# create a new application
app = QtGui.QApplication([])

Without this line of code, your application will have a hard crash, because at the C++ level, Qt cannot create any GUI components without a pre-existing QApplication having been defined.

This is generally the way you'll see most examples defined - but this is actually also deceptive.  If you know your script will be the root application, and run from a QApplication-free environment, then it is ok.

However, one of the ever changing factors of development particularly for the Film world, is the inclusion of Qt in multiple applications.  Maya 2012 for instance has switched to a Qt based core, and in fact most Autodesk products use Qt in one form or another by now.

While you need to make sure that there is a QApplication before running your Dialog - you need to make sure that there isn't a QApplication before creating a new one.

Qt will also crash out if more than 1 QApplication is instantiated at one time.

I have had a case of the same script working in Maya 2011 and failing in Maya 2012 because it was trying to create a new QApplication.

The best way to handle this, is to always check for a pre-existing instance before creating a new one.  If we change our above code to read:

# check for existing application
app = None
if ( not QtGui.QApplication.instance() ):
    # create a new application
    app = QtGui.QApplication.instance()

We are now ensuring that one and only one instance of an application will ever exist.

Final Code

So this is what our file will look like fully filled out for the Qt application:

#!/usr/bin/python ~/workspace/pyqt/helloworld/main.py

from PyQt4 import QtGui

if ( __name__ == '__main__' ):
    # define application pointer in case we create our own
    app = None

    # check to see if there is already a QApplication 
    # instance defined somewhere
    if ( not QtGui.QApplication.instance() ):
        app = QtGui.QApplication([])

    # popup a new dialog
    QtGui.QMessageBox.information( None, 'Hello', 'Hello, World!' )

No comments:

Post a Comment