4.2.1. Download, Compilation, and Running
This document guides the user on the creation of a new Python GUI Application, using Python, WAF modules and basic
Taurus and Qt functionality. As this is a programming tutorial, you will produce file and code as
instructued. You can also download a finalized version of the code from
https://gitlab.eso.org/ecos/cut/-/tree/master/examples/
, so our first step will be to download it.
$ git clone https://gitlab.eso.org/ecos/cut
$ mv cut/examples/python_application ./
$ rm -rf cut
The directory we will be using for this tutorial is the python_application
, and it contains the code for a
simple Python applicaiton. This is a waf project on its own, so it can be build in an independent manner from the rest
of Control UI Toolkit. In order to do so, the reader must execute:
$ cd python_application
$ waf configure install
And to execute the application:
$ cutPaeGui
4.2.2. Project Structure
This is the structure of the project. We use as build system WAF, and on top wtools extension to make ELT application definition more easier:
python_application/
├── PythonApplication
│ ├── src
│ │ ├── python_application_example
│ │ │ ├── applicationwindow.py
│ │ │ ├── __init__.py
│ │ │ └── mainwindow.ui
│ │ └── paegui.py
│ └── wscript
└── wscript
4.2.2.1. Project wscript
The first file we should take a look is python_application/wscript
:
1from wtools.project import declare_project
2
3def configure(cnf):
4 cnf.check_python_module('PySide2', condition="ver >= num(5, 14, 1) and ver <= num(6, 0, 0)")
5 cnf.check_python_module('taurus')
6 cnf.check_python_module('elt.cut')
7 cnf.check_python_module('CutWidgets')
8 cnf.check_python_module('CiiWidgets')
9
10declare_project('PythonApplicationExample', '2.3.1',
11 requires=['cxx',
12 'python',
13 'pyqt5'],
14 recurse='PythonApplication',
15 cxx_std='c++17')
16
The syntax of this file is that of python. WAF uses several wscript
files to describe its
project and modules build instructions.
The project is named PythonApplicationExample
, and this file is in charge of setting up dependencies. Here we check for the presence in our development environment of any required library or python module for the compilation and
execution of our application. In particular, we check for:
PySide2, which is the python bindings for Qt
taurus
elt.cut
CutWidgets
CiiWidgets
The declare_project()
method in line 10 includes under the require keyword the python
and pyqt5
strings,
which indicates that the included modules could be python programs.
Then, the recurse
list indicates which directory will be considered as module for this project. This WAF project has only 1 WAF module: PythonApplication
.
The PythonApplication
WAF module is the most important one. To create a basic UI application, we need the following files and directories.
One python package: the directory
PythonApplication/src/python_application_example
Its
__init__.py
fileAt least one UI file
mainwindow.ui
,The implementation of said UI file
applicationwindow.py
An entry point script
paegui.py
One
wscript
that handles the module.
4.2.2.2. Module wscript
python_application/PythonApplication/wscript
:
1#!/usr/bin/env python3
2from wtools import module
3
4# The declare_pyqt5program instruction will automatically find
5# the QT Resources, and the UI files, and run the necessary
6# commands to produce the python versions of them.
7
8module.declare_pyqt5program(
9 target='cutPaeGui',
10 py_program="src/paegui.py",
11 py_package="src/python_application_example",
12 use=[
13 "cut.widgets.bindings",
14 "cut.task",
15 ]
16)
This file uses the declare_pyqt5program
directive to instruct WAF that this module
produces an executable GUI application.
In line 9 the reader may find the target argument, which tells the name of the executable.
Independent of the py_program, when installing, the py_program is installed using the
target name into the $PREFIX/bin/
directory.
If the python application needs a package to be installed, the reader may specify it using
the py_package argument. This will be installed as a python package under
$PREFIX/lib/python$PYTHON_VERSION/site-packages/}
directory.
The use argument is to provide a list of dependencies this module has. Most importantly, these dependencies will be used also during tests.
For more details and information on wtools and WAF, please refer to their manuals.
4.2.3. Entry Point Python Script
The entry point python script paegui.py
is the one that creates a Qt GUI Application.
13 import sys
14 import click
15 import taurus
16 import taurus.cli.common
17 from taurus.qt.qtgui.application import TaurusApplication
18 from paegui import ApplicationWindow
taurus.qt.qtgui.application.TaurusApplication
inherits from QApplication, and it is in charge of application initialization, configuration of default values, logging, etc.
In this example, three taurus
utilities are used:
taurus.cli.common
provides common option parsers to both custom application and Taurusinternal tools. It is based in
click
and in this case, thelog_level
option is used. It will ensure that the format that we use to ask for the log level is the same through all applications.
21 @click.command("paegui")
22 @taurus.cli.common.log_level
23 def paegui(log_level):
24 ...
The code above is the beginning of the paegui
python method, which is the first one invoked
after the python intepreter enter the __main__
application entry point.
Since the parser for log_level
is already taken care of, the developer is free to use it
where they want. In this case the example forwards the log_level
value to the method
that sets the root logger’s level. See line 34.
28 app = TaurusApplication(
29 app_name = 'Python Application Example GUI',
30 app_version = '0.0.1',
31 org_name = 'ESO',
32 org_domain = 'eso.org',
33 )
34 taurus.setLogLevel(getattr(taurus, log_level))
35 window = ApplicationWindow()
36
37 window.show()
38 sys.exit(app.exec_())
39
40
41 if __name__ == "__main__":
42 paegui()
The last section of the main method is listed above. The most important part is the declaration of
app
, as a taurus.qt.qtgui.application.TaurusApplication
in line 28. This will
create a context where Qt and Taurus objects can exists.
In line 40 the user interface is instantiated by the creation of a ApplicationWindow
object,
which is then assigned to the window
variable. The ApplicationWindow
class is part of the
examples python package, and contains the implementation of the UI.
At this point, the application is ready to start, and to do so, we order it to show something in the screen. In this case, the GUI we have just loaded, using the show()
method.
But control is still under the script’s flow; developer most surrender control of the program, to Qt’s event loop. A program or a python script is a sequential flow of instructions. There can be decision points where the program flow to one section of the code to another, but in general terms, is a linear flow.
When we surrender control of the program to Qt event pump, Qt will constantly look in the system for inputs like keystrokes and mouse movements and click, and execute the appropriate methods. We have in fact changed from a sequential program, to an event-based one. Events are the deciding factor of the programs next instruction set.
To pass the control to the event pump, we invoke app.exec_()
method. This will leave the application in an endless loop governed by events.
See Definitions for more details on Asynchronous programming, Events, and Qt’s Event Engine.