Lecture 34 GUI - PyQt I

1. Introduction:

This is an introductory PyQt5 tutorial. The purpose of this tutorial is to get you started with the PyQt5 toolkit.

PyQt5 is a set of Python bindings for Qt5 application framework from Digia. It is available for the Python 2.x and 3.x. This tutorial uses Python 3. Qt library is one of the most powerful GUI libraries. The official home site for PyQt5 is www.riverbankcomputing.co.uk/news. PyQt5 is developed by Riverbank Computing. PyQt5 is implemented as a set of Python modules. It has over 620 classes and 6000 functions and methods. It is a multiplatform toolkit which runs on all major operating systems, including Unix, Windows, and Mac OS. PyQt5 is dual licensed. Developers can choose between a GPL and a commercial license.

PyQt5 modules PyQt5's classes are divided into several modules, including the following:

QtCore
QtGui
QtWidgets
QtMultimedia
QtBluetooth
QtNetwork
QtPositioning Enginio
QtWebSockets
QtWebKit
QtWebKitWidgets
QtXml
QtSvg
QtSql
QtTest

The QtCore module contains the core non-GUI functionality. This module is used for working with time, files and directories, various data types, streams, URLs, mime types, threads or processes. The QtGui contains classes for windowing system integration, event handling, 2D graphics, basic imaging, fonts and text. The QtWidgets module contains classes that provide a set of UI elements to create classic desktop-style user interfaces. The QtMultimedia contains classes to handle multimedia content and APIs to access camera and radio functionality. The QtBluetooth module contains classes to scan for devices and connect and interact with them. The QtNetwork module contains the classes for network programming. These classes facilitate the coding of TCP/IP and UDP clients and servers by making the network programming easier and more portable. The QtPositioning contains classes to determine a position by using a variety of possible sources, including satellite, Wi-Fi, or a text file. The Enginio module implements the client-side library for accessing the Qt Cloud Services Managed Application Runtime. The QtWebSockets module contains classes that implement the WebSocket protocol. The QtWebKit contains classes for a web browser implementation based on the WebKit2 library. The QtWebKitWidgets contains classes for a WebKit1 based implementation of a web browser for use in QtWidgets based applications.

The QtXml contains classes for working with XML files. This module provides implementation for both SAX and DOM APIs. The QtSvg module provides classes for displaying the contents of SVG files. Scalable Vector Graphics (SVG) is a language for describing two-dimensional graphics and graphical applications in XML. The QtSql module provides classes for working with databases. The QtTest contains functions that enable unit testing of PyQt5 applications.

2. QDate, QTime, QDateTime

PyQt5 has QDate, QDateTime, QTime classes to work with date and time. The QDate is a class for working with a calendar date in the Gregorian calendar. It has methods for determining the date, comparing, or manipulating dates. The QTime class works with a clock time. It provides methods for comparing time, determining the time and various other time manipulating methods. The QDateTime is a class that combines both QDate and QTime objects into one object.

Current date and time

PyQt5 has currentDate(), currentTime() and currentDateTime() methods for determining current date and time.

The currentDate() method returns the current date.




The date is printed in two different formats by passing the values Qt.ISODate and Qt.DefaultLocaleLongDate to the toString() method.



The currentDateTime() returns the current date and time. Finally, the currentTime() method returns the current time.



You don't have to remember and use all these date and time format. However, I recommend that if you can remember the '.currentDateTime()' method, you can do string slicing to take any information you are interested in the output:



Number of days in a particular month or year:

The number of days in a particular month is returned by the daysInMonth() method and the number of days in a year by the daysInYear() method.



Difference in days:



Datetime arithmetic:

We often need to add or subtract days, seconds, or years to a datetime value.



Daylight saving time:

Daylight saving time (DST) is the practice of advancing clocks during summer months so that evening daylight lasts longer. The time is adjusted forward one hour in the beginning of spring and adjusted backward in the autumn to standard time.



3. The first GUI window

This is a simple example showing a small window. Yet we can do a lot with this window. We can resize it, maximise it or minimise it. This requires a lot of coding. Someone already coded this functionality. Because it is repeated in most applications, there is no need to code it over again. PyQt5 is a high level toolkit. If we would code in a lower level toolkit, the following code example could easily have hundreds of lines.

The code below shows a small window on the screen. Here we provide the necessary imports. The basic widgets are located in PyQt5.QtWidgets module.



Every PyQt5 application must create an application object. The sys.argv parameter is a list of arguments from a command line. Python scripts can be run from the shell. It is a way how we can control the startup of our scripts.

The QWidget widget is the base class of all user interface objects in PyQt5. We provide the default constructor for QWidget. The default constructor has no parent. A widget with no parent is called a window.

The resize() method resizes the widget. It is 250px wide and 150px high.

The move() method moves the widget to a position on the screen at x=300, y=300 coordinates.

We set the title of the window with setWindowTitle(). The title is shown in the titlebar.

The show() method displays the widget on the screen. A widget is first created in memory and later shown on the screen.

Finally, we enter the mainloop of the application. The event handling starts from this point. The mainloop receives events from the window system and dispatches them to the application widgets. The mainloop ends if we call the exit() method or the main widget is destroyed. The sys.exit() method ensures a clean exit. The environment will be informed how the application ended. The exec_() method has an underscore. It is because the exec is a Python keyword. And thus, exec_() was used instead.

An application icon:

find a picture online in the '.png' format. Right click the figure and save it as 'web.png' to the same directory as your current '.py' file. Use the following code to add an icon to the window:


The previous example was coded in a procedural style. Python programming language supports both procedural and object oriented programming styles. Programming in PyQt5 means programming in OOP. Three important things in object oriented programming are classes, data, and methods. Here we create a new class called Example. The Example class inherits from the QWidget class. This means that we call two constructors: the first one for the Example class and the second one for the inherited class. The super() method returns the parent object of the Example class and we call its constructor. The __init__() method is a constructor method in Python language. The creation of the GUI is delegated to the initUI() method. All three methods have been inherited from the QWidget class. The setGeometry() does two things: it locates the window on the screen and sets it size. The first two parameters are the x and y positions of the window. The third is the width and the fourth is the height of the window. In fact, it combines the resize() and move() methods in one method. The last method sets the application icon. To do this, we have created a QIcon object. The QIcon receives the path to our icon to be displayed. The application and example objects are created. The main loop is started.

A push button:




In this example, we show a tooltip for two PyQt5 widgets.

This static method sets a font used to render tooltips. We use a 10pt SansSerif font. <b>QWidget</b> will bold the font. This is a CSS script.

To create a tooltip, we call the setTooltip() method. We can use rich text formatting.

We create a push button widget and set a tooltip for it.
The move() method moves the widget to a position on the screen at x=50, y=50 coordinates.

The button is being resized and moved on the window. The sizeHint() method gives a recommended size for the button.

Closing a window:



In this example, we create a quit button. Upon clicking on the button, the application terminates.

We create a push button. The button is an instance of the QPushButton class. The first parameter of the constructor is the label of the button. The second parameter is the parent widget. The parent widget is the Example widget, which is a QWidget by inheritance.

The event processing system in PyQt5 is built with the signal & slot mechanism. If we click on the button, the signal clicked is emitted. The slot can be a Qt slot or any Python callable. QCoreApplication, which is retrieved with QApplication.instance(), contains the main event loop—it processes and dispatches all events. The clicked signal is connected to the quit() method which terminates the application. The communication is done between two objects: the sender and the receiver. The sender is the push button, the receiver is the application object.

Message Box:

By default, if we click on the x button on the titlebar, the QWidget is closed. Sometimes we want to modify this default behaviour. For example, if we have a file opened in an editor to which we did some changes. We show a message box to confirm the action.



If we close a QWidget, the QCloseEvent is generated. To modify the widget behaviour we need to reimplement the closeEvent() event handler.

We show a message box with two buttons: Yes and No. The first string appears on the titlebar. The second string is the message text displayed by the dialog. The third argument specifies the combination of buttons appearing in the dialog. The last parameter is the default button. It is the button which has initially the keyboard focus. The return value is stored in the reply variable.

Centering window on a screen:

The following script shows how we can center a window on the desktop screen.



The QDesktopWidget class provides information about the user's desktop, including the screen size.

The code that will center the window is placed in the custom center() method.

We get a rectangle specifying the geometry of the main window. This includes any window frame.

We figure out the screen resolution of our monitor. And from this resolution, we get the center point.

Our rectangle has already its width and height. Now we set the center of the rectangle to the center of the screen. The rectangle's size is unchanged.

We move the top-left point of the application window to the top-left point of the qr rectangle, thus centering the window on our screen.


In this part of the PyQt5 tutorial, we have created simple code examples in PyQt5.








Tasks:

1. Start a new repository called 'PyQt_GUI' in your GitHub account. Code up all these examples in this tutorial in one .py file and 'push' it to your GUI repository. Send the link of the repository to the homework email.