Tuesday, April 3, 2018

Design GUI using PyQt5 on Raspberry Pi

Hello Everyone, In this post I will show you guys how to install PyQt5 on Raspberry Pi and then design beautiful user interfaces using PyQt5 running on Raspberry Pi. 
PyQt5 is a set of Python Bindings for Qt v5, the Qt version at the time of writing this post is Qt 5.10 and the corresponding Python Binding version is also the same.
PyQt5 Demo on Raspberry Pi with 3.5 inch TFT Display
The following video shows the demo of GUI designed using PyQt5, running on Raspberry Pi

Introduction
As a first step we need to install PyQt5 on our Raspberry Pi. I can share the command directly with you, but before that, I would like to introduce one very useful command with you, by this command you can verify the exact package name which you want to install.

  • apt-cache command
The apt-cache command can display much of the information stored in APT's internal database. This information is a sort of cache since it is gathered from the different sources listed in the sources.list file. This happens during the apt update operation.
Now the question arises that, how I will use the following command, so let's say, I want to install the PyQt5 on my Raspberry Pi, so i will use the following command.
apt-cache search pyqt5

After using the above command from Raspberry Pi terminal, it will provide list of all the packages which has name PyQt5 in it, and then from this list, we have to find the correct package.
apt-cache search pyqt5 result
From the above image we can clearly figure out that the PyQt5 package, which we want to install has name python3-pyqt5.
To install python packages we have to use the following command.
sudo apt-get install <package name>

To install PyQt5 package we will use the following command.
sudo apt-get install python3-pyqt5

Now PyQt5 is installed so as a next step we can design a small GUI application which will have one push button and on pressing the push button a message box is displayed. For this task you can use either Qt Designer tool or write code for all the controls. 
Writing code manually is good from learning perspective but it becomes very difficult to design complete user interface without any tool, that's why I prefer to use Qt Designer tool.
One can install this tool on your Raspberry Pi, but i don't prefer that, reason for this is speed limitation of Raspberry Pi as compared to Windows or other Linux based systems.
The following image display how Qt Designer looks and using the toolbox one can add as many controls.
Qt Designer
GUI with One Push Button in Qt Designer
Earlier we have posted one tutorial on designing GUI in Python using PyQt5, please click here to read that post.
Once design is ready, save the design file, this saved file will automatically have the extension name as *.ui.
Next step is to convert this *.ui file into Python *.py file, and this can be done by running a small program pyuic5.exe, which automatically gets installed when you installed pyqt5-tools python packages.
The following is the command to convert the design file (*.ui) into python program (*.py).
pyuic5.exe -x design_file.ui -o python_file.py

Once the above command is executed you will get the *.py file in your directory as shown in the image given below.
Python Code Generated from Design File
The python code is generated, but we haven't written anything for button press, so if you run the above auto-generated program, you will get nothing except the user interface.
As a next step, we have to add the code which will be executed when the push button on user interface is pressed, as you might also know that Qt works on signal and slot concept, and in this case of Push Button, clicking is a signal and then we have to add a slot for it, this will be done by adding the following code.
self.btn.clicked.connect( btn_clicked )

The above statement means, that whenever the push button named btn is clicked, the function btn_clicked will be executed.
def btn_clicked():
    print ("Button Pressed")
    QMessageBox.information(MainWindow, 'Welcome', 'PyQt5 Running on Raspberry Pi')

And the above btn_clicked function will display a message box with a welcome message.
The complete program is as follow.

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox


def btn_clicked():
    print ("Button Pressed")
    QMessageBox.information(MainWindow, 'Welcome', 'PyQt5 Running on Raspberry Pi')

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(284, 123)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btn = QtWidgets.QPushButton(self.centralwidget)
        self.btn.setGeometry(QtCore.QRect(60, 30, 151, 51))
        self.btn.setObjectName("btn")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Message Box Example"))
        self.btn.setText(_translate("MainWindow", "Click Me"))
        '''User Code'''
        self.btn.clicked.connect( btn_clicked )


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

The output of this program is shown in the image given below.
Program Running on Raspberry Pi
GitHub Link

In case of any feedback and suggestion please feel free to contact me.

2 comments:

  1. Which board and image do you use?
    I tested several combinations of boards and images but to fail.
    Qt does not work in many combinations.

    ReplyDelete
  2. Good afternoon my friend, congratulations for the explanation. Can you help me? I don't know how to update a label with the temperature value of a concentrated raspberry sensor. My GUI is frozen and does not update the label.

    ReplyDelete