Comprehensive PyQt5 Tutorial: Environment Setup, Basic Code Structure, Events, Signals & Slots, and QWidget Usage
This article provides a step‑by‑step guide to using PyQt5 for Python GUI development, covering installation, designer integration, converting .ui files to Python code, basic window structure, QObject concepts, event handling, signal‑slot mechanisms, common widget methods, and practical examples with full code snippets.
PyQt5 is a Python binding for the Qt GUI framework; mastering it helps testers and developers quickly build graphical tools and understand front‑end and back‑end integration.
1. Environment Setup
Install the required libraries using the following commands:
<code>pip install pyqt5 -i pypi.douban.com/simple</code> <code>pip install PySide2 -i pypi.douban.com/simple/ --trusted-host pypi.douban.com</code>Configure PyCharm to associate Qt Designer with the project and locate the pyuic5.exe conversion tool.
2. Basic Code Structure
The goal is to separate UI code from logic. Create a widget in Designer and save it as a .ui file, then convert it to Python:
<code>pyuic5 -o MyForm_UI.py MyForm.ui</code>Example of a runnable script for a widget:
<code>if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
Window = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Window)
Window.show()
sys.exit(app.exec_())</code>For a main window, inherit from QtWidgets.QMainWindow and use the generated UI class similarly.
3. QObject
All Qt objects inherit from QObject . Each object has a unique objectName that can be set in Designer. You can query or set dynamic properties:
<code>obj.objectName()
obj.setProperty('level1', 'first')
obj.property('level1')
obj.dynamicPropertyNames()</code>Objects can be deleted with obj.deleteLater() , which emits the destroyed signal.
4. Events, Signals, and Slots
4.1 Events
Widgets receive events such as mouse clicks, double‑clicks, key presses, and context‑menu requests. Overriding the event method allows custom handling before the default signal emission.
<code>class Btn(QPushButton):
def event(self, evt):
print(evt, "any signal passes through event")
return super().event(evt)
def mousePressEvent(self, evt):
print("mouse press")
return super().mousePressEvent(evt)
def mouseDoubleClickEvent(self, evt):
print("double click")
return super().mouseDoubleClickEvent(evt)</code>4.2 Signals
Signals can be emitted with or without parameters. Built‑in signals (e.g., clicked , valueChanged ) may carry data such as bool , int , or str . Custom signals are declared with pyqtSignal :
<code>class Btn(QPushButton):
rightSignal = pyqtSignal()
def mousePressEvent(self, evt):
super().mousePressEvent(evt)
if evt.button() == Qt.RightButton:
print('right button pressed')
self.rightSignal.emit()</code>Connecting signals to slots:
<code>btn.rightSignal.connect(custom_handler)
self.qsb.valueChanged[int].connect(lambda v: print(type(v)))
self.qsb.valueChanged[str].connect(lambda v: print(type(v)))</code>4.3 Slots
Slot functions must accept the same parameters as the signal they are connected to:
<code>def get_msg(a, b):
pass
def get_msg2(a):
pass
obj.sendmsged[str, int].connect(get_msg)
obj.sendmsged[str].connect(get_msg2)</code>5. QWidget Usage
Common widget events include showEvent , closeEvent , resizeEvent , mouse events ( mousePressEvent , mouseReleaseEvent , mouseMoveEvent ), and keyboard events ( keyPressEvent , keyReleaseEvent ). Example of mouse‑enter/leave handling:
<code>class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('Mouse Enter/Leave Demo')
self.resize(600, 500)
def enterEvent(self, event):
print('mouse entered')
self.setStyleSheet('background-color:red;')
def leaveEvent(self, event):
print('mouse left')
self.setStyleSheet('background-color:green;')
</code>Keyboard handling example:
<code>def keyPressEvent(self, event):
if event.key() == Qt.Key_5:
print('pressed 5')
if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_C:
print('ctrl + C')
if event.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and event.key() == Qt.Key_C:
print('ctrl + shift + C')
print('any other key')
def keyReleaseEvent(self, event):
print('key released')
</code>6. Common Widget Methods
Resize constraints, geometry, margins, stacking order, visibility, focus policy, and window flags can be controlled programmatically:
<code>widget.setMinimumSize(200, 200)
widget.setMaximumSize(500, 600)
widget.setGeometry(50, 200, 60, 30)
widget.setContentsMargins(50, 50, 10, 0)
label.lower()
label.raise_()
label.stackUnder(other_label)
widget.setWindowFlags(Qt.FramelessWindowHint)
widget.setWindowOpacity(0.7)
widget.setFocusPolicy(Qt.ClickFocus)
widget.setFocus()
</code>7. Custom Title Bar and Dragging
When using a frameless window, you can create custom close, maximize, and minimize buttons and implement mouse‑drag moving:
<code>class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.FramelessWindowHint)
self.setWindowOpacity(0.7)
self.init_buttons()
self.mouse_press = False
def init_buttons(self):
self.close_btn = QPushButton('Close', self)
self.max_btn = QPushButton('Maximize', self)
self.min_btn = QPushButton('Minimize', self)
self.close_btn.pressed.connect(self.close)
self.max_btn.pressed.connect(self.toggle_max)
self.min_btn.pressed.connect(self.showMinimized)
def toggle_max(self):
if self.isMaximized():
self.showNormal()
self.max_btn.setText('Maximize')
else:
self.showMaximized()
self.max_btn.setText('Restore')
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.mouse_press = True
self.win_x, self.win_y = self.x(), self.y()
self.m_x, self.m_y = event.globalX(), event.globalY()
def mouseMoveEvent(self, event):
if self.mouse_press:
dx = event.globalX() - self.m_x
dy = event.globalY() - self.m_y
self.move(self.win_x + dx, self.win_y + dy)
def mouseReleaseEvent(self, event):
self.mouse_press = False
</code>The article concludes with a reminder that the author will continue updating the tutorial series.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.