A Quick and Dirty Guide to PyQt5
So far I have seen a lot of guides that introduce the PyQt5 as the saviour of humanity, the holy hand grenade of all the GUIs out there, but I have not yet seen a guide where… well, you start with a basic stuff. Where you abuse the notation at first, make errors, just to get things going.
So here you go – a totally wrong, dirty guide to how not to write in PyQt5! With examples! And NO QML.
You can use any editor (Notepad, Kwrite, IDLE, Spyder) or even just the python console to write this stuff – don’t worry, it will work.
To get you started:
from PyQt5.QtWidgets import * app = QApplication([]) widget = QWidget() widget.show() app.exec()
Congratulations, you have your first QWidget on the screen! A blank, possibly gray widget, but a full widget in its graphical glory! Of course if you do not want a QWidget you can show anything else:
from PyQt5.QtWidgets import * app = QApplication([]) label = QLabel("Hello there") label.show() app.exec()
You want some interaction? Sure, let me stuff a label and a button inside a widget:
from PyQt5.QtWidgets import * app = QApplication([]) label = QLabel("hello there!") button = QPushButton("answer") layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(button) widget = QWidget() widget.setLayout( layout ) widget.show() app.exec()
This will make a vertical layout, stuff a label and a button inside, assign it to a widget and show it. Now we can connect() the signal from a button to any function:
from PyQt5.QtWidgets import * def answerTheButton(): label.setText("General Kenobi") app = QApplication([]) label = QLabel("hello there!") button = QPushButton("answer") button.pressed.connect(answerTheButton) layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(button) widget = QWidget() widget.setLayout( layout ) widget.show() app.exec()
What, you sayin’ I should not do that, I should use classes and be more careful with global variables? Nope, not here – it’s the dirty guide, remember? That’s why the third thing you will learn here is the usage of threads:
from PyQt5.QtWidgets import * from PyQt5.QtCore import * import time class EndlessCycle(QThread): def run(self): while True: if "hello" in label.text(): label.setText("General Kenobi") else: label.setText("hello there!") time.sleep(1) app = QApplication([]) thread = EndlessCycle() label = QLabel("hello there!") button = QPushButton("start the thread") button.pressed.connect(thread.start) layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(button) widget = QWidget() widget.setLayout( layout ) widget.show() app.exec()
As you can see – we only reimplemented a single function inside a QThread – run(), and … that’s pretty much it.
You want to stop the cycle? Add a boolean variable that will be checked every loop:
from PyQt5.QtWidgets import * from PyQt5.QtCore import * import time class EndlessCycle(QThread): keepDointIt = True def run(self): while self.keepDoingIt: if "hello" in label.text(): label.setText("General Kenobi") else: label.setText("hello there!") time.sleep(1) def stopCycle(): thread.keepDoingIt = False app = QApplication([]) thread = EndlessCycle() thread.keepDoingIt = True label = QLabel("hello there!") button = QPushButton("start the thread") button.pressed.connect(thread.start) button2 = QPushButton("stop the vicious cycle") button2.pressed.connect(stopCycle) layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(button) layout.addWidget(button2) widget = QWidget() widget.setLayout( layout ) widget.show() app.exec()
But we are using it essentially as a big timer (well, in a separate thread, but yeah), so can we use a QTimer? Sure:
from PyQt5.QtWidgets import * from PyQt5.QtCore import * class MyTimer(QTimer): def timerEvent(self,event): if "hello" in label.text(): label.setText("General Kenobi") else: label.setText("hello there!") app = QApplication([]) timer = MyTimer() timer.setInterval(1000) label = QLabel("hello there!") button = QPushButton("start the timer") button.pressed.connect(timer.start) layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(button) widget = QWidget() widget.setLayout( layout ) widget.show() app.exec()
Just a couple of side notes:
A usual set of imports in the following examples will be:
from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import *
A more elegant solution would be to use only
from PyQt5 import QtGui, QtWidgets, QtCore
and then use the full calls
widget = QtWidgets.QWidget() label = QtWidgets.QLabel()
but you will need to remember by heart which classes are where, which is not always that logical.