Introduction to PyQt5(GUI in Python)
Introduction
PyQt is a GUI widgets toolkit. It is a Python interface for Qt, one of the most powerful, and popular cross-platform GUI library. PyQt was developed by RiverBank Computing Ltd. The latest version of PyQt can be downloaded from its official website − riverbankcomputing.com
PyQt API is a set of modules containing a large number of classes and functions. While QtCore module contains non-GUI functionality for working with file and directory etc., QtGui module contains all the graphical controls. In addition, there are modules for working with XML (QtXml), SVG (QtSvg), and SQL (QtSql), etc.
Features of PyQT
Here are important features of PyQt:
Learn PyQt which consists of more than six hundred classes covering a range of features such as
- Graphical User Interfaces
- SQL Databases
- Web toolkits
- XML processing
- Networking
Supporting Environments
PyQt is compatible with all the popular operating systems including Windows, Linux, and Mac OS. It is dual licensed, available under GPL as well as commercial license. The latest stable version is PyQt5–5.13.2.
Windows
Wheels for 32-bit or 64-bit architecture are provided that are compatible with Python version 3.5 or later. The recommended way to install is using PIP utility −
pip3 install PyQt5
To install development tools such as Qt Designer to support PyQt5 wheels, following is the command −
pip3 install pyqt5-tools
You can also build PyQt5 on Linux/macOS from the source code www.riverbankcomputing.com/static/Downloads/PyQt5
What is New?
PyQt5 API is not automatically compatible with earlier versions. Hence, Python code involving PyQt4 modules should be upgraded manually by making relevant changes. In this chapter, main differences between PyQt4 and PyQt5 have been listed.
PyQt5 is not supported on versions of Python earlier than v2.6.
PyQt5 doesn’t support connect() method of QObject class for connection between signal and slot. Hence the usage can no more be implemented −
QObject.connect(widget, QtCore.SIGNAL(‘signalname’), slot_function)
Only the following syntax is defined −
widget.signal.connect(slot_function)
Classes defined in earlier QtGui module have been distributed in QtGui, QtPrintSupport an QtWidgets modules.
In the new QFileDialog class, The getOpenFileNameAndFilter() method is replaced by getOpenFileName(), getOpenFileNamesAndFilter() by getOpenFileNames() and getSaveFileNameAndFilter() by getSaveFileName(). Older signatures of these methods also have changed.
PyQt5 doesn’t have provision to define a class that is sub-classed from more than one Qt class.
pyuic5 utility (to generates Python code from Designer’s XML file) does not support the — pyqt3-wrapper flag.
pyrcc5 does not support the -py2 and -py3 flags. The output of pyrcc5 is compatible with all versions of Python v2.6 onwards.
PyQt5 always invokes sip.setdestroyonexit() automatically and calls the C++ destructor of all wrapped instances that it owns
Components and Widgets
There is a large number of widgets available in PyQt for creating GUI apps. However, with PyQt5, there has been a reshuffling of classes into different modules and revisions in the licenses.
Therefore, it’s crucial to have a high-level view of the structure of PyQt5. In this section, you will see how PyQt5 is organized internally and learn about the different modules, libraries, and API classes provided by PyQt5.
PyQt5 Directory Structure
These are the fundamental modules used by Python’s Qt binding, specifically PyQt5.
- Qt: It combines all the classes/modules mentioned below into a single module. It considerably increases the memory used by the application. However, it’s easier to manage the framework by only importing one module.
- QtCore: Contains the core non-graphical classes used by other modules. This is where the Qt event loop, signals, and slot-connectivity, etc. are implemented.
- QtWidgets: Contains most of the widgets available in Pyqt5.
- QtGui: Contains GUI components and extends the QtCore module.
- QtNetwork: Contains classes used to implement network programming through Qt. It supports TCP servers, TCP sockets, UDP sockets, SSL handling, network sessions, and DNS lookups.
- QtMultimedia provides low-level multimedia functionality.
- QtSql: implements database integration for SQL databases. Supports ODBC, MySQL, Oracle, SQLite, and PostgreSQL.
PyQt5 Widgets
Here is a list of the most frequently used widgets in PyQt5
- QLineEdit: This is an input field which allows one line of text to be entered by the user.
line = QLineEdit()
- QRadioButton: This is an input field with a selectable button, similar to the radio buttons in html.
rad = QRadioButton("button title")
rad.setChecked(True) #to select the button by default.
- QComboBox: It is used to display a dropdown menu with a list of selectable items.
drop = QComboBox(w)
drop.addItems(["item one", "item two", "item three"])
- QCheckBox: Displays a selectable square box in front of the label that is ticked if selected, similar to radio buttons.
check = QCheckBox("button title")
- QMenuBar: it displays a horizontal menu bar at the top of a window. You can only add objects of the QMenu class to this bar. Those QMenu objects can further contain strings, QAction objects or other QMenu objects.
- QToolBar: It is a horizontal bar or pane which can be moved within the window. It may contain buttons and other widgets.
- QTab: it is used to break down the contents of a window into multiple pages that can be accessed through different tabs on top of the widget. It consists of two sections: the tab bar and the tab page.
- QScrollBar: It is used to create scroll bars which allow the user to scroll up and down within a window. It consists of a movable slider, a slider track, and two buttons to scroll the slider up or down.
scroll = QScrollBar()
- QSplitter: Splitters are used to separate the contents of a window so that the widgets are grouped properly and do not appear cluttered. QSplitter is one of the primary layout handlers available in PyQt5 and is used to split the content both horizontally and vertically.
- QDock: A dock widget is a sub-window with two properties:
- It can be moved within the main window and
- It can be docked outside the parent window to another location on the screen.
Layouts and Themes
In the previous PyQt5 examples, you have only been using the move() and resize() methods to set the positions of widgets in your GUI.
However, PyQt has a robust layout management engine which can be used to create advanced user interfaces for applications. In this section, you will learn about two important classes that are used in Qt to create and manage layouts.
- QBoxLayout
- QGridLayout
QBoxLayout
QBoxLayout is used to align the child widgets of the layout in a horizontal or vertical row. The two classes of interest that inherit from QBoxLayout are:
- QHBoxLayout: used to line the child widgets horizontally.
- QVBoxLayout: used to line the child widgets vertically.
For example, this is how three buttons aligned with QHBoxLayout will look.
import sys
from PyQt5.QtWidgets import *if __name__ == "__main__": app = QApplication([])
w = QWidget()
w.setWindowTitle("Musketeers") btn1 = QPushButton("Athos")
btn2 = QPushButton("Porthos")
btn3 = QPushButton("Aramis") hbox = QHBoxLayout(w) hbox.addWidget(btn1)
hbox.addWidget(btn2)
hbox.addWidget(btn3) w.show() sys.exit(app.exec_())
And this is how they will look in QVBoxLayout.
import sys
from PyQt5.QtWidgets import *if __name__ == "__main__": app = QApplication([])
w = QWidget()
w.setWindowTitle("Musketeers") btn1 = QPushButton("Athos")
btn2 = QPushButton("Porthos")
btn3 = QPushButton("Aramis") vb = QVBoxLayout(w) vb.addWidget(btn1)
vb.addWidget(btn2)
vb.addWidget(btn3) w.show() sys.exit(app.exec_())
The only function that needs any explanation at this point is the addWidget() method. It is used to insert widgets into the HBox or VBox layout. It is also used in other layouts where it takes a different number of parameters as you will see in the next section. The widgets will appear inside the layout in the order in which you insert them.
QGridLayout
QGridLayout is used to create interfaces in which the widgets are laid out in the form of a grid (like a matrix or 2D array). To insert elements in a grid layout, you can use the matrix representation to define the number of rows and columns in the grid as well as the position of those elements.
For example, to create a 3*3 grid (i.e., a grid with three rows and three columns), you will write the following code:
Import sys
from PyQt5.QtWidgets import *if __name__ == "__main__":
app = QApplication([]) w = QWidget() grid = QGridLayout(w) for i in range(3):
for j in range(3):
grid.addWidget(QPushButton("Button"),i,j)
w.show()
sys.exit(app.exec_())
This will be the output:
The addWidget() method In the grid layout takes these arguments:
- The widget object that you want to add to the grid
- The x-coordinate of the object
- The y-coordinate of the object
- The row-span (default =0)
- The col-span (default=0)
To understand it better, you can manually insert each widget as shown below
import sys
from PyQt5.QtWidgets import *if __name__ == "__main__":
app = QApplication([]) w = QWidget() grid = QGridLayout(w)
grid.addWidget(QPushButton("Button one"),0,0)
grid.addWidget(QPushButton("Button two"),0,1)
grid.addWidget(QPushButton("Button three"),1,0)
grid.addWidget(QPushButton("Button four"),1,1)
w.show()
sys.exit(app.exec_())
This is what the grid will look like:
You can also pass the rowspan and colspan parameters to addWidget() in order to span more than one row or column.
For example,
grid.addWidget(QPushButton("Button five"),2,0,1,0)
This will create a button that stretches over both columns.
Themes
PyQt5 comes with some built-in themes that you can use in your apps. The setStyle() method called on the QApplication instance is used to set a particular theme to your application.
For example, adding the following line of code will change the theme of your application from default to Fusion
app.setStyle("Fusion")
This is how the previous example will look in Fusion Theme
Another useful function for theming your apps is the setPalette() method. Here’s the code for changing the colour of different widgets using setPalette().
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPaletteif __name__ == "__main__":
app = QApplication([])
app.setStyle("Fusion")
qp = QPalette()
qp.setColor(QPalette.ButtonText, Qt.black)
qp.setColor(QPalette.Window, Qt.black)
qp.setColor(QPalette.Button, Qt.gray)
app.setPalette(qp) w = QWidget() grid = QGridLayout(w)
grid.addWidget(QPushButton("Button one"),0,0)
grid.addWidget(QPushButton("Button two"),0,1)
grid.addWidget(QPushButton("Button three"),1,0)
grid.addWidget(QPushButton("Button four"),1,1)
w.show()
sys.exit(app.exec_())
Here’s the result.
To use the setPalette() method, you first need to define a palette. This is done by creating an object of the QPalette class.
qp = QPalette()
Notice that the QPalette class belongs to the QtGui module and you will need to import it for this to work. Once you’ve created the QPalette object, use the setColor() method to pass the name of a widget whose colour you want to change and the colour you want to be set.
qp.setColor(QPalette.Window, Qt.black)
This will change the colour of the window to black. After you have defined your color-scheme, use the setPalette() function to apply the palette to your application.
app.setPalette(qp)
That is all you need to do if you want to create some basic themes for your app. PyQt also allows you to use stylesheets to define the look of your widgets. If you are familiar with CSS, you can easily define advanced styles for your app using Qt Style Sheets.
References:
https://riverbankcomputing.com/software/pyqt
https://build-system.fman.io/pyqt5-tutorial
https://zetcode.com/gui/pyqt5/