This post participates in the contest
"Smart phones for smart posts"
The web has a certain amount of information on the
PySide project, but not a lot of Russian.
This article is an attempt to fill this gap. Next will be described the assembly of the project, running applications on the emulator, an example of creating your own binding. Some key features of
PySide will be shown through examples.
Introduction What is PySide?
PySide is a project to create a
Qt binding to the
Python programming
language . It aims to implement support for all
Qt features, including
QtQuick and
QtMobility . The following component versions and platforms are currently supported.
Qt | 4.6, 4.7, 4.8 betta |
QtMobility | 1.2.0 |
Python | 2.5, 2.6, 2.7, 3.2 (experemental) |
OS | Linux / X11, Maemo 5, MeeGo, Windows, Mac OS X |
There is no opportunity to use
PySide on Symbian yet (or I don’t know this possibility), but according to the developers, work is being done in this direction. Alternatively, you can use PyS60, although it has nothing to do with
Qt , so we will not talk further about it later.
')
The
PySide project also contains a set of tools that allow you to bind any libraries written in C / C ++. In more detail we will talk about these tools further.
PySide is licensed under the LGPL, i.e. It can be used in both open and closed commercial projects.
PySide source code is open and available at the following address
github.com/PySide . Also, if you find any problems related to
PySide , you can report them to the
project's official
bug tracker .
PySide build, health check
The
download page provides instructions for installing
PySide on various operating systems. But it may happen that for your Linux distribution, such a package is not available. We will assemble it ourselves, which is not at all difficult, since even here, the Qt developers took care of their users, and prepared a set of scripts that maximally automate the build operations of
PySide .
So, to begin to clone a Git repository with build scripts. We don't need anything else yet, because dependencies will be cloned all the necessary projects.
$ git clone git://github.com/PySide/BuildScripts.git buildscripts $ cd buildscripts $ git submodule init $ git submodule update
You may have several versions of
Qt installed on your system. To specify which version to use, edit the enviroment.sh file in which you list the path to the
Qt home directory and the path where
PySide will be installed. The enviroment.sh file is provided with detailed comments, so you should have no difficulties. Immediately I warn you that
PySide may not build up with the default
Qt version installed on the system. I recommend using the latest QtSdk build.
Once everything is set up, build
PySide with the command
$ ./build_and_install
To facilitate the work, the enviroment.sh file is easily converted into a script, with the help of which applications that run
PySide are launched. All you need to do is make it executable and add
python $ @ to the end.
To test the performance of the received package, we clone the repository with
Qt examples in
Python , adapted for
PySide $ git clone git://github.com/PySide/Examples.git pyside-examples
and run any of your favorite examples, for example Hyper UI



Now we are ready to build
PySide for the host system. But during development, it may be convenient to run applications in the simulator, which is included in the QtSdk distribution. Let's collect
PySide and for it. To do this, edit the QT_SDK_HOME variable in the enviroment.sh file, specifying the path to the QtSimulator ($ {YOUPATH} / QtSDK / Simulator / Qt / gcc) as the
Qt home directory. You also need to edit the build_and_install file: you need to add the -DQ_WS_SIMULATOR = yes option to the cmake startup command. This option helps cmake determine the platform under which the compilation will take place.
If you start the build now, then at the moment it unfortunately will end in failure, because QtWebKit module cannot build. I created a
report on this error to which I attached a small patch that fixes this problem. But as of this writing, this bug has not yet been fixed. Therefore, use this patch for a complete
PySide build under QtSimulator (see the attachment to the bug report at the link above).


Nothing prevents us from collecting the
QtMobility binding for the QtSimulator. Its assembly is no different from the assembly of
PySide itself.
QtMobility will be assembled and will even run in the simulator, but unfortunately, not one of the modules at the same time can be called a worker. None of the examples supplied with
QtMobility itself, nor from the
pyside-examples package, has
earned in full . I will still understand the reasons for this and, perhaps, someday I'll write about it.

Introduction to programming on PySide. Signals and slots, property system
This section is not an introduction to the
Python programming
language . Here, it will only show how to use some of the key features of Qt in
Python .
Signal-slot interaction
from PySide import QtCore def say_hello(name): print "Hello,", name class Foo(QtCore.QObject): @QtCore.Slot(str) def say_bye(self, name): print "Bye,", name class Bar(QtCore.QObject): signal = QtCore.Signal(tuple) f = Foo() b = Bar() b.signal.connect(say_hello) b.signal.connect(f.say_bye) b.signal.emit("User.") b.signal.emit(1.25)
Signal is the class through which the connection of the signal and the slot is controlled, as well as the sending of the signal itself. The types of parameters transmitted with the signal are specified when it is created. It can be any type of C and
Python . If we want to send parameters of a different type (as in the example above), the type must be tuple or list. As before, the signal must be declared within the class inherited from QObject.
If you need to create multiple signals, you can use the following form
class Test(QtCore.QObject): signals = QtCore.Signal((int,), (str,), (float, QtCore.QObject))
This code will add three signals with the signatures signals (int), signals (QString) and signals (double, QObject *). All of them are contained in the variable signals, which can be considered as a dictionary (not iterable). The signal parameters are used as the key.
someone.signals.emit(10)
A slot can be any class method that is not necessarily inherited from QObject, a global function, or even a lambda function. But such objects are not true slots, in QMetaObject there is no information about them, so use this approach with caution. For example, if you use a global function as a slot, then you cannot get information about the calling object in it.
In order to create a true slot, you need to use the Slot decorator from the QtCore module. In code, it looks like this:
@QtCore.Slot(int) @QtCore.Slot(str) def mySlot(value): print value
For slots, overload signal rules do not apply and we cannot create a slot accepting any type of parameters. For each type of parameter, a separate decorator should be added. The above is an example of a slot that can accept parameters of type int and QString.
Both the QtCore.Signal class and the QtCore.Slot decorator can take as additional parameters the name under which the generated signals and slots will be stored in object-specific information. By default, if the name is not specified, the signal is assigned the name of the class member to which it is assigned, and the name of the method to be decorated is assigned to the slot. A slot can also specify the type of return value. You can use similar functionality for
Python and
QML communication.
You can read more about the interaction between
Python and
QML at
developer.qt.nokia.com in the Python section. You can also see examples of
pyside-qml-examples .
Property system
Working with
Qt properties is not much different from working with classic
Python properties. Just give a small example.
from PySide import QtCore class MyObject(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) self._x = None def getx(self): print "get" return self._x def setx(self, val): print "set" self._x = val prop = QtCore.Property(int, getx, setx) obj = MyObject() obj.prop = 12345 print obj.prop
More details about working with
Qt properties in
Python can be read
here .
Creating a GUI using PySide
The
PySide Tools package includes standard Qt tools for working with application resources, developing a “classic” graphical interface, and localizing applications. These are pyside-ui, pyside-rcc and pyside-lupdate. Working with them is no different from the same packages for Qt / C ++. Therefore, you still have the opportunity to create a graphic application framework in QtDesigner. The resulting form is compiled using pyside-ui, which as input parameters you need to specify the form file and the output file, through the option -o. Pyside-ui also has an additional interesting option, -x, which adds application launch code to the resulting
Python file. Below is a small example of launching an application using a form created in a designer, resources and localization
from PySide import QtCore, QtGui from form_ui import *
Also in
PySide , many
Qt goodies from recent years are available, including QtQuick. Those. we have the ability to create hybrid applications using
Python and
QML (QtQuick.Particles, Qt Desktop Components, etc.).
An example of creating your own binding
Knowing all the above, we can create our own
Python applications using
Qt , including those using QtQuick. But what if we need to use the library written in C / C ++ with our project or use our previous work done on the same C / C ++? Do not rewrite everything again in
Python ?
For example, we have a certain project using
Qt Components . All main functionality is written in
QML . But to launch it, you need the
QmlDesktopViewer class already written in C ++. It will not be difficult for us to rewrite it in
Python , but it would not be interesting right now. Let's make our own binding of this class to
Python .
To do this, use the tools from the
PySide project to create bindings. These are API Extractor, Shiboken and Generator Runner. We already have all these tools.
To create a binding, you first need to create an xml file that describes what data we are going to export, hide, rename, etc. In general, what we will get access to in the resulting
Python module.
<?xml version="1.0"?> <typesystem package="PySide.QmlDesktopViewer"> <load-typesystem name="typesystem_declarative.xml" generate="no" /> <rejection class="*" function-name="x11Event" /> <object-type name="LoggerWidget" /> <object-type name="QmlDesktopViewer" /> </typesystem>
I specifically described in detail what files we get at the output of the generator, since they are the ones to be compiled to get the
Python module. Understanding this will make it easier to write the project file for the build system you are using. For more information on the rules for compiling this file, see the
API Extractor documentation.
The next step is to create a header file for the C ++ language, which will extract information about the data for which the binding is made.
#undef QT_NO_STL #undef QT_NO_STL_WCHAR #ifndef NULL #define NULL 0 #endif #include "pyside_global.h" #include <loggerwidget.h> #include <qmldesktopviewer.h>
We received the pyside_global.h file during
PySide assembly. You can copy it to the project or add a path to its location.
I use CMake as a build system. I will not describe the assembly here. The full sample code can be found
here . You can use it as an example to create your own binding.
We compile the project, and we get a library with a wrapper over our class, which we can use in our
Python application. We use this module to launch one of the examples of Qt Desktop Components.

I also want to note that several bindings of third-party libraries already exist for
PySide . One of them is the
Qwt binding.
Materials used
PySide v1.0.8 documentationPySide Mobility v0.2.2 documentationNew-style signal / slotPySide on the Developer Network
Running PySide applications on Qt SimulatorPySide Binding GeneratorPySide Binding Generation Tutorial