PyQt5 - Quick Guide

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.
A list of frequently used modules is given below −
QtCore − Core non-GUI classes used by other modules
QtCore − Core non-GUI classes used by other modules
QtGui − Graphical user interface components
QtGui − Graphical user interface components
QtMultimedia − Classes for low-level multimedia programming
QtMultimedia − Classes for low-level multimedia programming
QtNetwork − Classes for network programming
QtNetwork − Classes for network programming
QtOpenGL − OpenGL support classes
QtOpenGL − OpenGL support classes
QtScript − Classes for evaluating Qt Scripts
QtScript − Classes for evaluating Qt Scripts
QtSql − Classes for database integration using SQL
QtSql − Classes for database integration using SQL
QtSvg − Classes for displaying the contents of SVG files
QtSvg − Classes for displaying the contents of SVG files
QtWebKit − Classes for rendering and editing HTML
QtWebKit − Classes for rendering and editing HTML
QtXml − Classes for handling XML
QtXml − Classes for handling XML
QtWidgets − Classes for creating classic desktop-style UIs
QtWidgets − Classes for creating classic desktop-style UIs
QtDesigner − Classes for extending Qt Designer
QtDesigner − Classes for extending Qt Designer
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.
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
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.
Creating a simple GUI application using PyQt involves the following steps −
Import QtCore, QtGui and QtWidgets modules from PyQt5 package.
Import QtCore, QtGui and QtWidgets modules from PyQt5 package.
Create an application object of QApplication class.
Create an application object of QApplication class.
A QWidget object creates top level window. Add QLabel object in it.
A QWidget object creates top level window. Add QLabel object in it.
Set the caption of label as "hello world".
Set the caption of label as "hello world".
Define the size and position of window by setGeometry() method.
Define the size and position of window by setGeometry() method.
Enter the mainloop of application by app.exec_() method.
Enter the mainloop of application by app.exec_() method.
Following is the code to execute Hello World program in PyQt −
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QLabel(w)
   b.setText("Hello World!")
   w.setGeometry(100,100,200,50)
   b.move(50,20)
   w.setWindowTitle("PyQt5")
   w.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   window()
The above code produces the following output −
It is also possible to develop an object oriented solution of the above code.
Import QtCore, QtGui and QtWidgets modules from PyQt5 package.
Import QtCore, QtGui and QtWidgets modules from PyQt5 package.
Create an application object of QApplication class.
Create an application object of QApplication class.
Declare window class based on QWidget class
Declare window class based on QWidget class
Add a QLabel object and set the caption of label as "hello world".
Add a QLabel object and set the caption of label as "hello world".
Define the size and position of window by setGeometry() method.
Define the size and position of window by setGeometry() method.
Enter the mainloop of application by app.exec_() method.
Enter the mainloop of application by app.exec_() method.
Following is the complete code of the object oriented solution −
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(200,50)
      self.setWindowTitle("PyQt5")
      self.label = QLabel(self)
      self.label.setText("Hello World")
      font = QFont()
      font.setFamily("Arial")
      font.setPointSize(16)
      self.label.setFont(font)
      self.label.move(50,20)
def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
PyQt API is a large collection of classes and methods. These classes are defined in more than 20 modules.
Following are some of the frequently used modules −
QtCore
Core non-GUI classes used by other modules
QtGui
Graphical user interface components
QtMultimedia
Classes for low-level multimedia programming
QtNetwork
Classes for network programming
QtOpenGL
OpenGL support classes
QtScript
Classes for evaluating Qt Scripts
QtSql
Classes for database integration using SQL
QtSvg
Classes for displaying the contents of SVG files
QtWebKit
Classes for rendering and editing HTML
QtXml
Classes for handling XML
QtWidgets
Classes for creating classic desktop-style UIs.
QtDesigner
Classes for extending Qt Designer
QtAssistant
Support for online help
PyQt5 development tools is a collection of useful utilities for Qt development. Following is a select list of such utilities −
assistant
Qt Assistant documentation tool
pyqt5designer
Qt Designer GUI layout tool
linguist
Qt Linguist translation tool
lrelease
compile ts files to qm files
pylupdate5
extract translation strings and generate or update ts files
qmake
Qt software build tool
pyqt5qmlscene
QML file viewer
pyqmlviewer
QML file viewer
pyrcc5
Qt resource file compiler
pyuic5
Qt User Interface Compiler for generating code from ui files
pyqmltestrunner
running unit tests on QML code
qdbus
command-line tool to list D-Bus services
QDoc
documentation generator for software projects.
Qhelpgenerator
generating and viewing Qt help files.
qmlimportscanner
parses and reports on QML imports
PyQt API contains more than 400 classes. The QObject class is at the top of class hierarchy. It is the base class of all Qt objects. Additionally, QPaintDevice class is the base class for all objects that can be painted.
QApplication class manages the main settings and control flow of a GUI application. It contains main event loop inside which events generated by window elements and other sources are processed and dispatched. It also handles system-wide and application-wide settings.
QWidget class, derived from QObject and QPaintDevice classes is the base class for all user interface objects. QDialog and QFrame classes are also derived from QWidget class. They have their own sub-class system.
Here is a select list of frequently used widgets
QLabel
Used to display text or image
QLineEdit
Allows the user to enter one line of text
QTextEdit
Allows the user to enter multi-line text
QPushButton
A command button to invoke action
QRadioButton
Enables to choose one from multiple options
QCheckBox
Enables choice of more than one options
QSpinBox
Enables to increase/decrease an integer value
QScrollBar
Enables to access contents of a widget beyond display aperture
QSlider
Enables to change the bound value linearly.
QComboBox
Provides a dropdown list of items to select from
QMenuBar
Horizontal bar holding QMenu objects
QStatusBar
Usually at bottom of QMainWindow, provides status information.
QToolBar
Usually at top of QMainWindow or floating. Contains action buttons
QListView
Provides a selectable list of items in ListMode or IconMode
QPixmap
Off-screen image representation for display on QLabel or QPushButton object
QDialog
Modal or modeless window which can return information to parent window
A typical GUI based application’s top level window is created by QMainWindow widget object. Some widgets as listed above take their appointed place in this main window, while others are placed in the central widget area using various layout managers.
The following diagram shows the QMainWindow framework −
The PyQt installer comes with a GUI builder tool called Qt Designer. Using its simple drag and drop interface, a GUI interface can be quickly built without having to write the code. It is however, not an IDE such as Visual Studio. Hence, Qt Designer does not have the facility to debug and build the application.
Start Qt Designer application which is a part of development tools and installed in scripts folder of the virtual environment.
Start designing GUI interface by choosing File → New menu.
You can then drag and drop required widgets from the widget box on the left pane. You can also assign value to properties of widget laid on the form.
The designed form is saved as demo.ui. This ui file contains XML representation of widgets and their properties in the design. This design is translated into Python equivalent by using pyuic5 command line utility. This utility is a wrapper for uic module of Qt toolkit. The usage of pyuic5 is as follows −
pyuic5 -x demo.ui -o demo.py

In the above command, -x switch adds a small amount of additional code to the generated Python script (from XML) so that it becomes a self-executable standalone application.
if __name__ == "__main__":
   import sys
   app = QtGui.QApplication(sys.argv)
   Dialog = QtGui.QDialog()
   ui = Ui_Dialog()
   ui.setupUi(Dialog)
   Dialog.show()
   sys.exit(app.exec_())
The resultant python script is executed to show the following dialog box −
python demo.py

The user can input data in input fields but clicking on Add button will not generate any action as it is not associated with any function. Reacting to user-generated response is called as event handling.
Unlike a console mode application, which is executed in a sequential manner, a GUI based application is event driven. Functions or methods are executed in response to user’s actions like clicking on a button, selecting an item from a collection or a mouse click etc., called events.
Widgets used to build the GUI interface act as the source of such events. Each PyQt widget, which is derived from QObject class, is designed to emit ‘signal’ in response to one or more events. The signal on its own does not perform any action. Instead, it is ‘connected’ to a ‘slot’. The slot can be any callable Python function.
First design a simple form with a LineEdit control and a PushButton.
It is desired that if button is pressed, contents of text box should be erased. The QLineEdit widget has a clear() method for this purpose. Hence, the button’s clicked signal is to be connected to clear() method of the text box.
To start with, choose Edit signals/slots from Edit menu (or press F4). Then highlight the button with mouse and drag the cursor towards the textbox
As the mouse is released, a dialog showing signals of button and methods of slot will be displayed. Select clicked signal and clear() method
The Signal/Slot Editor window at bottom right will show the result −
Save ui and Build and Python code from ui file as shown in the below code −
pyuic5 -x signalslot.ui -o signalslot.py

Generated Python code will have the connection between signal and slot by the following statement −
self.pushButton.clicked.connect(self.lineEdit.clear)

Run signalslot.py and enter some text in the LineEdit. The text will be cleared if the button is pressed.
Instead of using Designer, you can directly establish signal-slot connection by following syntax −
widget.signal.connect(slot_function)

Suppose if a function is to be called when a button is clicked. Here, the clicked signal is to be connected to a callable function. It can be achieved in any of the following technique −
button.clicked.connect(slot_function)

In the following example, two QPushButton objects (b1 and b2) are added in QDialog window. We want to call functions b1_clicked() and b2_clicked() on clicking b1 and b2 respectively.
When b1 is clicked, the clicked() signal is connected to b1_clicked() function −
b1.clicked.connect(b1_clicked())

When b2 is clicked, the clicked() signal is connected to b2_clicked() function.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   win = QDialog()
   b1 = QPushButton(win)
   b1.setText("Button1")
   b1.move(50,20)
   b1.clicked.connect(b1_clicked)
   
   b2 = QPushButton(win)
   b2.setText("Button2")
   b2.move(50,50)
   b2.clicked.connect(b2_clicked)
   
   win.setGeometry(100,100,200,100)

   win.setWindowTitle("PyQt5")
   win.show()
   sys.exit(app.exec_())

def b1_clicked():
   print ("Button 1 clicked")

def b2_clicked():
   print ("Button 2 clicked")

if __name__ == '__main__':
   window()
The above code produces the following output −
Button 1 clicked
Button 2 clicked

A GUI widget can be placed inside the container window by specifying its absolute coordinates measured in pixels. The coordinates are relative to the dimensions of the window defined by setGeometry() method.
QWidget.setGeometry(xpos, ypos, width, height)

In the following code snippet, the top level window of 300 by 200 pixels dimensions is displayed at position (10, 10) on the monitor.
import sys
from PyQt4 import QtGui

def window():
   app = QtGui.QApplication(sys.argv)
   w = QtGui.QWidget()
	
   b = QtGui.QPushButton(w)
   b.setText("Hello World!")
   b.move(50,20)
	
   w.setGeometry(10,10,300,200)
   w.setWindowTitle(“PyQt”)
   w.show()
   sys.exit(app.exec_())
	
if __name__ == '__main__':
   window()
A PushButton widget is added in the window and placed at a position 50 pixels towards right and 20 pixels below the top left position of the window.
This Absolute Positioning, however, is not suitable because of following reasons −
The position of the widget does not change even if the window is resized.
The position of the widget does not change even if the window is resized.
The appearance may not be uniform on different display devices with different resolutions.
The appearance may not be uniform on different display devices with different resolutions.
Modification in the layout is difficult as it may need redesigning the entire form.
Modification in the layout is difficult as it may need redesigning the entire form.
PyQt API provides layout classes for more elegant management of positioning of widgets inside the container. The advantages of Layout managers over absolute positioning are −
Widgets inside the window are automatically resized.
Widgets inside the window are automatically resized.
Ensures uniform appearance on display devices with different resolutions.
Ensures uniform appearance on display devices with different resolutions.
Adding or removing widget dynamically is possible without having to redesign.
Adding or removing widget dynamically is possible without having to redesign.
Qt toolkit defines various layouts that can be used with Qt Designer utility.
Here is the list of Classes which we will discuss one by one in this chapter.
QBoxLayout class lines up the widgets vertically or horizontally. Its derived classes are QVBoxLayout (for arranging widgets vertically) and QHBoxLayout (for arranging widgets horizontally).
A GridLayout class object presents with a grid of cells arranged in rows and columns. The class contains addWidget() method. Any widget can be added by specifying the number of rows and columns of the cell.
QFormLayout is a convenient way to create two column form, where each row consists of an input field associated with a label. As a convention, the left column contains the label and the right column contains an input field.
Here is the list of Widgets which we will discuss one by one in this chapter.
A QLabel object acts as a placeholder to display non-editable text or image, or a movie of animated GIF. It can also be used as a mnemonic key for other widgets.
QLineEdit object is the most commonly used input field. It provides a box in which one line of text can be entered. In order to enter multi-line text, QTextEdit object is required.
In PyQt API, the QPushButton class object presents a button which when clicked can be programmed to invoke a certain function.
A QRadioButton class object presents a selectable button with a text label. The user can select one of many options presented on the form. This class is derived from QAbstractButton class.
A rectangular box before the text label appears when a QCheckBox object is added to the parent window. Just as QRadioButton, it is also a selectable button.
A QComboBox object presents a dropdown list of items to select from. It takes minimum screen space on the form required to display only the currently selected item.
A QSpinBox object presents the user with a textbox which displays an integer with up/down button on its right.
QSlider class object presents the user with a groove over which a handle can be moved. It is a classic widget to control a bounded value.
A horizontal QMenuBar just below the title bar of a QMainWindow object is reserved for displaying QMenu objects.
A QToolBar widget is a movable panel consisting of text buttons, buttons with icons or other widgets.
This is a preconfigured dialog with a text field and two buttons, OK and Cancel. The parent window collects the input in the text box after the user clicks on Ok button or presses Enter.
Another commonly used dialog, a font selector widget is the visual appearance of QDialog class. Result of this dialog is a Qfont object, which can be consumed by the parent window.
This widget is a file selector dialog. It enables the user to navigate through the file system and select a file to open or save. The dialog is invoked either through static functions or by calling exec_() function on the dialog object.
If a form has too many fields to be displayed simultaneously, they can be arranged in different pages placed under each tab of a Tabbed Widget. The QTabWidget provides a tab bar and a page area.
Functioning of QStackedWidget is similar to QTabWidget. It also helps in the efficient use of window’s client area.
This is another advanced layout manager which allows the size of child widgets to be changed dynamically by dragging the boundaries between them. The Splitter control provides a handle that can be dragged to resize the controls.
A dockable window is a subwindow that can remain in floating state or can be attached to the main window at a specified position. Main window object of QMainWindow class has an area reserved for dockable windows.
QMainWindow object reserves a horizontal bar at the bottom as the status bar. It is used to display either permanent or contextual status information.
QListWidget class is an item-based interface to add or remove items from a list. Each item in the list is a QListWidgetItem object. ListWidget can be set to be multiselectable.
A scrollbar control enables the user to access parts of the document that is outside the viewable area. It provides visual indicator to the current position.
QCalendar widget is a useful date picker control. It provides a month-based view. The user can select the date by the use of the mouse or the keyboard, the default being today’s date.
A QDialog widget presents a top level window mostly used to collect response from the user. It can be configured to be Modal (where it blocks its parent window) or Modeless (the dialog window can be bypassed).
PyQt API has a number of preconfigured Dialog widgets such as InputDialog, FileDialog, FontDialog, etc.
In the following example, WindowModality attribute of Dialog window decides whether it is modal or modeless. Any one button on the dialog can be set to be default. The dialog is discarded by QDialog.reject() method when the user presses the Escape key.
A PushButton on a top level QWidget window, when clicked, produces a Dialog window. A Dialog box doesn’t have minimize and maximize controls on its title bar.
The user cannot relegate this dialog box in the background because its WindowModality is set to ApplicationModal.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   btn = QPushButton(w)
   btn.setText("Hello World!")
   btn.move(100,50)
   btn.clicked.connect(showdialog)
   w.setWindowTitle("PyQt Dialog demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   dlg = QDialog()
   b1 = QPushButton("ok",dlg)
   b1.move(50,50)
   dlg.setWindowTitle("Dialog") 9. PyQt5 — QDialog Class
   dlg.setWindowModality(Qt.ApplicationModal)
   dlg.exec_()

if __name__ == '__main__':
   window()
The above code produces the following output. Click on button in main window and dialog box pops up −
QMessageBox is a commonly used modal dialog to display some informational message and optionally ask the user to respond by clicking any one of the standard buttons on it. Each standard button has a predefined caption, a role and returns a predefined hexadecimal number.
Important methods and enumerations associated with QMessageBox class are given in the following table −
setIcon()
Displays predefined icon corresponding to severity of the message
Question
Information
Warning
Critical
setText()
Sets the text of the main message to be displayed
setInformativeText()
Displays additional information
setDetailText()
Dialog shows a Details button. This text appears on clicking it
setTitle()
Displays the custom title of dialog
setStandardButtons()
List of standard buttons to be displayed. Each button is associated with
QMessageBox.Ok 0x00000400
QMessageBox.Open 0x00002000
QMessageBox.Save 0x00000800
QMessageBox.Cancel 0x00400000
QMessageBox.Close 0x00200000
QMessageBox.Yes 0x00004000
QMessageBox.No 0x00010000
QMessageBox.Abort 0x00040000
QMessageBox.Retry 0x00080000
QMessageBox.Ignore 0x00100000
setDefaultButton()
Sets the button as default. It emits the clicked signal if Enter is pressed
setEscapeButton()
Sets the button to be treated as clicked if the escape key is pressed
In the following example, click signal of the button on the top level window, the connected function displays the messagebox dialog.
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText("This is a message box")
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
msg.setDetailedText("The details are as follows:")

setStandardButton() function displays desired buttons.
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)

buttonClicked() signal is connected to a slot function, which identifies the caption of source of the signal.
msg.buttonClicked.connect(msgbtn)

The complete code for the example is as follows −
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   w = QWidget()
   b = QPushButton(w)
   b.setText("Show message!")
   
   b.move(100,50)
   b.clicked.connect(showdialog)
   w.setWindowTitle("PyQt MessageBox demo")
   w.show()
   sys.exit(app.exec_())

def showdialog():
   msg = QMessageBox()
   msg.setIcon(QMessageBox.Information)
   
   msg.setText("This is a message box")
   msg.setInformativeText("This is additional information")
   msg.setWindowTitle("MessageBox demo")
   msg.setDetailedText("The details are as follows:")
   msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
   msg.buttonClicked.connect(msgbtn)

   retval = msg.exec_()

def msgbtn(i):
   print ("Button pressed is:",i.text())

if __name__ == '__main__':
   window()
The above code produces the following output. Message Box pops up when main windows’ button is clicked −
If you click on Ok or Cancel button on MessageBox, the following output is produced on the console −
Button pressed is: OK
Button pressed is: Cancel

A typical GUI application may have multiple windows. Tabbed and stacked widgets allow to activate one such window at a time. However, many a times this approach may not be useful as view of other windows is hidden.
One way to display multiple windows simultaneously is to create them as independent windows. This is called as SDI (single Document Interface). This requires more memory resources as each window may have its own menu system, toolbar, etc.
MDI (Multiple Document Interface) applications consume lesser memory resources. The sub windows are laid down inside main container with relation to each other. The container widget is called QMdiArea.
QMdiArea widget generally occupies the central widget of QMainWondow object. Child windows in this area are instances of QMdiSubWindow class. It is possible to set any QWidget as the internal widget of subWindow object. Sub-windows in the MDI area can be arranged in cascaded or tile fashion.
The following table lists important methods of QMdiArea class and QMdiSubWindow class −
addSubWindow()
Adds a widget as a new subwindow in MDI area
removeSubWindow()
Removes a widget that is internal widget of a subwindow
setActiveSubWindow()
Activates a subwindow
cascadeSubWindows()
Arranges subwindows in MDiArea in a cascaded fashion
tileSubWindows()
Arranges subwindows in MDiArea in a tiled fashion
closeActiveSubWindow()
Closes the active subwindow
subWindowList()
Returns the list of subwindows in MDI Area
setWidget()
Sets a QWidget as an internal widget of a QMdiSubwindow instance
QMdiArea object emits subWindowActivated() signal whereas windowStateChanged() signal is emitted by QMdisubWindow object.
In the following example, top level window comprising of QMainWindow has a menu and MdiArea.
self.mdi = QMdiArea()
self.setCentralWidget(self.mdi)
bar = self.menuBar()
file = bar.addMenu("File")

file.addAction("New")
file.addAction("cascade")
file.addAction("Tiled")
Triggered() signal of the menu is connected to windowaction() function.
file.triggered[QAction].connect(self.windowaction)

The new action of menu adds a subwindow in MDI area with a title having an incremental number to it.
MainWindow.count = MainWindow.count+1
sub = QMdiSubWindow()
sub.setWidget(QTextEdit())
sub.setWindowTitle("subwindow"+str(MainWindow.count))
self.mdi.addSubWindow(sub)
sub.show()
Cascaded and tiled buttons of the menu arrange currently displayed subwindows in cascaded and tiled fashion respectively.
The complete code is as follows −
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class MainWindow(QMainWindow):
   count = 0

   def __init__(self, parent = None):
      super(MainWindow, self).__init__(parent)
      self.mdi = QMdiArea()
      self.setCentralWidget(self.mdi)
      bar = self.menuBar()

      file = bar.addMenu("File")
      file.addAction("New")
      file.addAction("cascade")
      file.addAction("Tiled")
      file.triggered[QAction].connect(self.windowaction)
      self.setWindowTitle("MDI demo")

   def windowaction(self, q):
      print ("triggered")
   
      if q.text() == "New":
         MainWindow.count = MainWindow.count+1
         sub = QMdiSubWindow()
         sub.setWidget(QTextEdit())
         sub.setWindowTitle("subwindow"+str(MainWindow.count))
         self.mdi.addSubWindow(sub)
         sub.show()

      if q.text() == "cascade":
         self.mdi.cascadeSubWindows()

      if q.text() == "Tiled":
         self.mdi.tileSubWindows()

def main():
   app = QApplication(sys.argv)
   ex = MainWindow()
   ex.show()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()
Run above code and three windows in cascased and tiled formation −
The provision of drag and drop is very intuitive for the user. It is found in many desktop applications where the user can copy or move objects from one window to another.
MIME based drag and drop data transfer is based on QDrag class. QMimeData objects associate the data with their corresponding MIME type. It is stored on clipboard and then used in the drag and drop process.
The following QMimeData class functions allow the MIME type to be detected and used conveniently.
Many QWidget objects support the drag and drop activity. Those that allow their data to be dragged have setDragEnabled() which must be set to true. On the other hand, the widgets should respond to the drag and drop events in order to store the data dragged into them.
DragEnterEvent provides an event which is sent to the target widget as dragging action enters it.
DragEnterEvent provides an event which is sent to the target widget as dragging action enters it.
DragMoveEvent is used when the drag and drop action is in progress.
DragMoveEvent is used when the drag and drop action is in progress.
DragLeaveEvent is generated as the drag and drop action leaves the widget.
DragLeaveEvent is generated as the drag and drop action leaves the widget.
DropEvent, on the other hand, occurs when the drop is completed. The event’s proposed action can be accepted or rejected conditionally.
DropEvent, on the other hand, occurs when the drop is completed. The event’s proposed action can be accepted or rejected conditionally.
In the following code, the DragEnterEvent verifies whether the MIME data of the event contains text. If yes, the event’s proposed action is accepted and the text is added as a new item in the ComboBox.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class combo(QComboBox):
   def __init__(self, title, parent):
      super(combo, self).__init__( parent)
      self.setAcceptDrops(True)

   def dragEnterEvent(self, e):
      print (e)

      if e.mimeData().hasText():
         e.accept()
      else:
         e.ignore()

   def dropEvent(self, e):
      self.addItem(e.mimeData().text())

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()

      self.initUI()

   def initUI(self):
      lo = QFormLayout()
      lo.addRow(QLabel("Type some text in textbox and drag it into combo box"))
   
      edit = QLineEdit()
      edit.setDragEnabled(True)
      com = combo("Button", self)
      lo.addRow(edit,com)
      self.setLayout(lo)
      self.setWindowTitle('Simple drag and drop')
def main():
   app = QApplication(sys.argv)
   ex = Example()
   ex.show()
   app.exec_()

if __name__ == '__main__':
   main()
The above code produces the following output −
PyQt5 library contains QtSql module. It is an elaborate class system to communicate with many SQL based databases. Its QSqlDatabase provides access through a Connection object. Following is the list of currently available SQL drivers −
QDB2
IBM DB2
QIBASE
Borland InterBase Driver
QMYSQL
MySQL Driver
QOCI
Oracle Call Interface Driver
QODBC
ODBC Driver (includes Microsoft SQL Server)
QPSQL
PostgreSQL Driver
QSQLITE
SQLite version 3 or above
QSQLITE2
SQLite version 2
For this chapter, a connection with a SQLite database is established using the static method −
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sports.db')

Other methods of QSqlDatabase class are as follows −
setDatabaseName()
Sets the name of the database with which connection is sought
setHostName()
Sets the name of the host on which the database is installed
setUserName()
Specifies the user name for connection
setPassword()
Sets the connection object’s password if any
commit()
Commits the transactions and returns true if successful
rollback()
Rolls back the database transaction
close()
Closes the connection
QSqlQuery class has the functionality to execute and manipulate SQL commands. Both DDL and DML type of SQL queries can be executed. First step is to create SQlite database using the following statements −
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('sportsdatabase.db')

Next, obtain Query object with QSqlQuery() method and call its most important method exec_(), which takes as an argument a string containing SQL statement to be executed.
query = QtSql.QSqlQuery()
query.exec_("create table sportsmen(id int primary key, " "firstname varchar(20), lastname varchar(20))")

The following script creates a SQLite database sports.db with a table of sportsperson populated with five records.
import sys
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def createDB():
   db = QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sportsdatabase.db')

   if not db.open():
      msg = QMessageBox()
      msg.setIcon(QMessageBox.Critical)
      msg.setText("Error in Database Creation")
      retval = msg.exec_()
      return False
   query = QSqlQuery()

   query.exec_("create table sportsmen(
      id int primary key, ""firstname varchar(20), lastname varchar(20))")

   query.exec_("insert into sportsmen values(101, 'Roger', 'Federer')")
   query.exec_("insert into sportsmen values(102, 'Christiano', 'Ronaldo')")
   query.exec_("insert into sportsmen values(103, 'Ussain', 'Bolt')")
   query.exec_("insert into sportsmen values(104, 'Sachin', 'Tendulkar')")
   query.exec_("insert into sportsmen values(105, 'Saina', 'Nehwal')")
   return True

if __name__ == '__main__':
   app = QApplication(sys.argv)
   createDB()
To confirm that the SQLite database is created with above records added in sportsmen table in it, use a SQLite Gui utility called SQLiteStudio.
QSqlTableModel class in PyQt is a high-level interface that provides editable data model for reading and writing records in a single table. This model is used to populate a QTableView object. It presents to the user a scrollable and editable view that can be put on any top level window.
A QSqlTableModel object is declared in the following manner −
model = QtSql.QSqlTableModel()

Its editing strategy can be set to any of the following −
In the following example, sportsperson table is used as a model and the strategy is set as −
model.setTable('sportsmen') 
model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
   model.select()
QTableView class is part of Model/View framework in PyQt. The QTableView object is created as follows −
view = QtGui.QTableView()
view.setModel(model)
view.setWindowTitle(title)
return view
This QTableView object and two QPushButton widgets are added to the top level QDialog window. Clicked() signal of add button is connected to addrow() which performs insertRow() on the model table.
button.clicked.connect(addrow)
def addrow():
   print model.rowCount()
   ret = model.insertRows(model.rowCount(), 1)
   print ret
The Slot associated with the delete button executes a lambda function that deletes a row, which is selected by the user.
btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))

The complete code is as follows −
import sys
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def initializeModel(model):
   model.setTable('sportsmen')
   model.setEditStrategy(QSqlTableModel.OnFieldChange)
   model.select()
   model.setHeaderData(0, Qt.Horizontal, "ID")
   model.setHeaderData(1, Qt.Horizontal, "First name")
   model.setHeaderData(2, Qt.Horizontal, "Last name")

def createView(title, model):
   view = QTableView()
   view.setModel(model)
   view.setWindowTitle(title)
   return view

def addrow():
   print (model.rowCount())
   ret = model.insertRows(model.rowCount(), 1)
   print (ret)

def findrow(i):
   delrow = i.row()

if __name__ == '__main__':
   app = QApplication(sys.argv)
   db = QSqlDatabase.addDatabase('QSQLITE')
   db.setDatabaseName('sportsdatabase.db')
   model = QSqlTableModel()
   delrow = -1
   initializeModel(model)

   view1 = createView("Table Model (View 1)", model)
   view1.clicked.connect(findrow)

   dlg = QDialog()
   layout = QVBoxLayout()
   layout.addWidget(view1)

   button = QPushButton("Add a row")
   button.clicked.connect(addrow)
   layout.addWidget(button)

   btn1 = QPushButton("del a row")
   btn1.clicked.connect(lambda: model.removeRow(view1.currentIndex().row()))
   layout.addWidget(btn1)

   dlg.setLayout(layout)
   dlg.setWindowTitle("Database Demo")
   dlg.show()
   sys.exit(app.exec_())
The above code produces the following output −
Try adding and deleting a few records and go back to SQLiteStudio to confirm the transactions.
All the QWidget classes in PyQt are sub classed from QPaintDevice class. A QPaintDevice is an abstraction of two dimensional space that can be drawn upon using a QPainter. Dimensions of paint device are measured in pixels starting from the top-left corner.
QPainter class performs low level painting on widgets and other paintable devices such as printer. Normally, it is used in widget’s paint event. The QPaintEvent occurs whenever the widget’s appearance is updated.
The painter is activated by calling the begin() method, while the end() method deactivates it. In between, the desired pattern is painted by suitable methods as listed in the following table.
begin()
Starts painting on the target device
drawArc()
Draws an arc between the starting and the end angle
drawEllipse()
Draws an ellipse inside a rectangle
drawLine()
Draws a line with endpoint coordinates specified
drawPixmap()
Extracts pixmap from the image file and displays it at the specified position
drwaPolygon()
Draws a polygon using an array of coordinates
drawRect()
Draws a rectangle starting at the top-left coordinate with the given width and height
drawText()
Displays the text at given coordinates
fillRect()
Fills the rectangle with the QColor parameter
setBrush()
Sets a brush style for painting
setPen()
Sets the color, size and style of pen to be used for drawing
In the following code, various methods of PyQt's drawing methods are used.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()
      self.initUI()

   def initUI(self):
      self.text = "hello world"
      self.setGeometry(100,100, 400,300)
      self.setWindowTitle('Draw Demo')
      self.show()

   def paintEvent(self, event):
      qp = QPainter()
      qp.begin(self)
      qp.setPen(QColor(Qt.red))
      qp.setFont(QFont('Arial', 20))
      qp.drawText(10,50, "hello Python")
      qp.setPen(QColor(Qt.blue))
      qp.drawLine(10,100,100,100)
      qp.drawRect(10,150,150,100)
      qp.setPen(QColor(Qt.yellow))
      qp.drawEllipse(100,50,100,50)
      qp.drawPixmap(220,10,QPixmap("pythonlogo.png"))
      qp.fillRect(20,175,130,70,QBrush(Qt.SolidPattern))
      qp.end()

def main():
   app = QApplication(sys.argv)
   ex = Example()
   sys.exit(app.exec_())

if __name__ == '__main__':
   main()
The above code produces the following output −
In this chapter, we shall learn Brush Style Constants.
Given below are the Brush Style Constants −
Given below are the Predefined QColor Styles −
Given below are the Predefined QColor Objects −
The QClipboard class provides access to system-wide clipboard that offers a simple mechanism to copy and paste data between applications. Its action is similar to QDrag class and uses similar data types.
QApplication class has a static method clipboard() which returns reference to clipboard object. Any type of MimeData can be copied to or pasted from the clipboard.
Following are the clipboard class methods that are commonly used −
clear()
Clears clipboard contents
setImage()
Copies QImage into clipboard
setMimeData()
Sets MIME data into clipboard
setPixmap()
Copies Pixmap object in clipboard
setText()
Copies QString in clipboard
text()
Retrieves text from clipboard
Signal associated with clipboard object is −
dataChanged()
Whenever clipboard data changes
In the following example, two TextEdit objects and two Pushbuttons are added to a top level window.
To begin with the clipboard object is instantiated. Copy() method of textedit object copies the data onto the system clipboard. When the Paste button is clicked, it fetches the clipboard data and pastes it in other textedit object.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Example(QWidget):
   def __init__(self):
      super(Example, self).__init__()

      self.initUI()

   def initUI(self):
      hbox = QVBoxLayout()
      self.edit1=QTextEdit()
      hbox.addWidget(self.edit1)
      self.btn1=QPushButton("Copy")
      hbox.addWidget(self.btn1)
      self.edit2=QTextEdit()
      self.btn2=QPushButton("Paste")
      hbox.addWidget(self.edit2)
      hbox.addWidget(self.btn2)
      self.btn1.clicked.connect(self.copytext)
      self.btn2.clicked.connect(self.pastetext)
      self.setLayout(hbox)
      
      self.setGeometry(300, 300, 300, 200)
      self.setWindowTitle('Clipboard')
      self.show()
      
   def copytext(self):

      #clipboard.setText(self.edit1.copy())
      self.edit1.copy()
      print (clipboard.text())

      msg=QMessageBox()
      msg.setText(clipboard.text()+" copied on clipboard")
      msg.exec_()

   def pastetext(self):
      self.edit2.setText(clipboard.text())

app = QApplication(sys.argv)
clipboard=app.clipboard()
ex = Example()
ex.setWindowTitle("clipboard Example")
sys.exit(app.exec_())
The above code produces the following output −
QPixmap class provides an off-screen representation of an image. It can be used as a QPaintDevice object or can be loaded into another widget, typically a label or button.
Qt API has another similar class QImage, which is optimized for I/O and other pixel manipulations. Pixmap, on the other hand, is optimized for showing it on screen. Both formats are interconvertible.
The types of image files that can be read into a QPixmap object are as follows −
Following methods are useful in handling QPixmap object −
copy()
Copies pixmap data from a QRect object
fromImage()
Converts QImage object into QPixmap
grabWidget()
Creates a pixmap from the given widget
grabWindow()
Create pixmap of data in a window
Load()
Loads an image file as pixmap
save()
Saves the QPixmap object as a file
toImage
Converts a QPixmap to QImage
The most common use of QPixmap is to display image on a label/button.
The following example shows an image displayed on a QLabel by using the setPixmap() method.
The complete code is as follows −
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
   app = QApplication(sys.argv)
   win = QWidget()
   l1 = QLabel()
   l1.setPixmap(QPixmap("python.png"))

   vbox = QVBoxLayout()
   vbox.addWidget(l1)
   win.setLayout(vbox)
   win.setWindowTitle("QPixmap Demo")
   win.show()
   sys.exit(app.exec_())

if __name__ == '__main__':
   window()
The above code produces the following output −

    146 Lectures 
     22.5 hours 

 ALAA EID
 Print
 Add Notes
 Bookmark this page