PyQt5介绍和案例(主要为案例)
PyQt5是一个Python封装的Qt5 GUI框架,可用于开发跨平台桌面应用。本文介绍了PyQt5的核心模块(QtWidgets、QtCore等)、基本窗口控件(QWidget、QMainWindow)、常用UI组件(按钮、标签、输入框等)和布局管理器(垂直/水平/网格布局)。重点讲解了信号槽机制实现事件处理,并通过一个案例演示了可拖动标签和按钮交互功能:3个按钮分别实现ID增减和位数显示,同时
一. PyQt5介绍
1. PyQt5 是什么?
PyQt5 是 Python 对 Qt5 库的完整封装。Qt 是一个跨平台的 C++ GUI 框架,PyQt 让你能用 Python 调用 Qt 的功能,快速构建桌面应用。
核心特点:
-
跨平台:Windows、macOS、Linux
-
功能丰富:GUI、绘图、数据库、网络、多线程等
-
面向对象:与 Python 风格完美契合
-
两种许可:GPL(开源免费)和商业许可
2. 基本架构理解
主要模块:
PyQt5.QtWidgets # 窗口控件(最常用)
PyQt5.QtCore # 核心功能(信号槽、事件等)
PyQt5.QtGui # 图形界面组件
PyQt5.QtMultimedia # 多媒体
PyQt5.QtWebEngine # 网页引擎
3. 各部分模块介绍
(1)窗口
1. QWidget
控件和窗口的父类,自由度高(什么都东西都没有),没有划分菜单、工具栏、状态栏、主窗口 等区域
2. QMainWindow
是 QWidget 的子类,包含菜单栏,工具栏,状态栏,标题栏等,中间部分则为主窗口区域
3. QDialog
对话框窗口的基类
基本使用
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
# 设置窗口标题
w.setWindowTitle("第一个PyQt")
# 展示窗口
w.show()
# 程序进行循环等待状态
app.exec()
文字说明:
-
只要是 Qt 制作的 app,必须有且只有 1 个
QApplication对象 -
sys.argv当做参数的目的是将运行时的命令参数传递给QApplication对象 -
创建了一个
QWidget对象,将它的标题设置为 “第一个 PyQt” -
然后调用
show方法显示出来 -
程序开始运行程序,直到关闭了窗口
QWidget窗口调整(其实是通用的,这些方法控件啥的也都能用,后面也会有演示)
w.resize(w, h) # 设置窗口的w, h
w.move(x, y) # 设置窗口的x, y
w.frameGeometry().getRect() # 获取当前窗口的x, y, w, h
w.setWindowIcon(QIcon('xxx.png')) # 设置图标,QIcon是QTGui里的
w.setLayout(xxx) # 设置布局
w.setStyleSheet("background-color:grey;") # 设置样式
QMainWindow 窗口调整
file_menu = menu.addMenu("文件")
file_menu.addAction("新建")
file_menu.addAction("打开")
file_menu.addAction("保存")
edit_menu = menu.addMenu("编辑")
edit_menu.addAction("复制")
edit_menu.addAction("粘贴")
edit_menu.addAction("剪切")
(2)控件
按钮
from PyQt5.QtWidgets import QPushButton
btn = QPushButton("btn")
btn.setParent(xxx) # 里头填QWidget对象或者其他
标签
from PyQt5.QtWidgets import QLabel
text = QLabel("btn", xxx) # 就等于之前的创建加设置父亲,只是两步合为一步,分开写也行
text.setGeometry(x, y, w, h) # 设置位置与大小,其他控件也可以
text.setStyleSheet("background-color:grey;") # 设置样式
text.resize(x, y) # 设置大小
text.setWordWrap(True) # 自动换行
text.setAlignment(Qt.AlignTop) # 靠上
text.repaint() # 更新内容
输入框
edit = QLineEdit(w)
edit.setPlaceholderText("please input ... ")
edit.setGeometry(x, y, w, h)
滚动条
scroll = QScrollArea()
scrollsetWidget(xxx)
(3)布局
- QBoxLayout
- QGridLayout
- QFormLayout
- QStackedLayout
1、QBoxLayout
QVBoxLayout(垂直布局)
layout = QVBoxLayout # 创建布局器
w.setLayout(layout) # 使用布局器
对于之前让控件显示都是设置父对象,现在可以直接 layout.addWidget(btn) 就达到了相同效果
layout.addStretch(2) # 添加一个伸缩器(理解成弹簧,和加的位置有关,这个参数就是一个比例关系,就理解成弹簧系数)
QHBoxLayout(水平布局)
同垂直布局
2、QGridLayout(网格布局/九宫格布局)
grid = QGridLayout()
grid.addwidget(btn, line_num, col_num) # 添加哪个控件,添加到第几行第几个
3、QFormLayout(form表单)
4、QStackedLayout(抽屉布局)
每个抽屉都用QWidget新建,而后再用addWidget加入抽屉布局
随后可以用setCurrentInder(0)来选择显示哪个Widget,0代表加入的第一个
5、分组
hobby = QGroupBox("爱好")
hobby.setLayout(xxx)
# 可以创建一个组,组里再设置布局,同时组也可以放入别人的布局器
# 比如实现下图这种结构,hobby是垂直,gender是水平,
# 最后再把他两调用setLayout都放入一个垂直布局器

(4)信号和槽
概念
1. 信号 (signal)
其实就是事件(按钮点击、内容发生改变、窗口的关闭事件)或者是状态(check 选中了,togglebutton 切换。)当程序触发了某种状态或者发生了某种事件(比如:按钮被点击了,内容改变等等),那么即可发射出来一个信号。
2. 槽 (slot)
若想捕获这个信号,然后执行相应的逻辑代码,那么就需要使用到槽,槽实际上是一个函数,当信号发射出来后,会执行与之绑定的槽函数。
3. 将信号与槽链接
为了能够实现,当点击某个按钮时执行某个逻辑,需要把具体的信号和具体的槽函数绑定到一起。
使用
对象.信号.connect(槽函数) # 绑定槽函数
对象.信号.emit(参数) # 发射信号
pyqtSignal(str) # 自定义信号,(str)表示接收一个参数,类型是str
二. 案例
案例介绍:有一个标签显示id和标签所在的坐标,三个按钮分别对应三个功能:按下后id+1,按下后id-1,用0显示id有几位(如12345就显示00000),同时还要完成标签可拖动,拖动的同时显示的坐标也要求事实变化
import sys
from PyQt5.Qt import QObject
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout, QGroupBox
id = 123
label = None
def incr_id():
global id, label
id += 1
update_label()
label.repaint()
def decre_id():
global id, label
id -= 1
update_label()
label.repaint()
def showZero():
global id, label
num = len(str(id)) if id != 0 else 1
print("0的个数为:" + "0"*num)
from PyQt5.QtWidgets import QMessageBox
QMessageBox.information(None, "0的个数", "0"*num)
def update_label():
global id, label
label.setText(f"{id} postion: {label.x()} , {label.y()}")
class DraggableLable(QLabel):
def __init__(self, text, parent):
super().init__(text, parent)
self.setMouseTracking(True)
self.offset = None
self.setStyleSheet("border: 2px solid red; padding: 5px;")
def mousePressEvent(self, ev):
if ev.button() == Qt.LeftButton:
self.offset = ev.pos()
super().mousePressEvent(ev)
def mouseMoveEvent(self, ev):
if ev.buttons() & Qt.LeftButton and self.offset is not None:
new_pos = self.parent().mapFromGlobal(ev.globalPos()) - self.offset
self.move(new_pos)
self.setText(str(id) + " position:" + str(self.x()) + " , " + str(self.y()))
super().mouseMoveEvent(ev)
def mouseReleaseEvent(self, ev):
if ev.button() == Qt.LeftButton:
self.offset = None
super().mouseReleaseEvent(ev)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = QWidget()
contain = QVBoxLayout()
hlayout = QHBoxLayout()
w.setWindowTitle("PyQt5 Test")
label = DragableLable(str(id) + " positon: 226 , 100", w)
label.setGeometry(226, 100, 300, 60)
btn_group = QGroupBox("按钮")
btn1 = QPushButton("Btn1")
btn1.clicked.connect(incr_id)
btn1.setStyleSheet("border: 2px solid red; padding: 5px;")
hlayout.addWidget(btn1)
btn2 = QPushButton("Btn2")
btn2.clicked.connect(decre_id)
btn2.setStyleSheet("border: 2px solid red; padding: 5px;")
hlayout.addWidget(btn2)
btn3 = QPushButton("Btn3")
btn3.clicked.connect(showZero)
btn3.setStyleSheet("border: 2px solid red; padding: 5px;")
hlayout.addWidget(btn3)
btn_group.setLayout(hlayout)
contain.addStretch(3)
contain.addWidget(btn_group)
contain.addStretch(1)
w.resize(700, 450)
w.move(2000, 600)
w.setLayout(contain)
w.show()
app.exec_()
说明
1、可拖拽类继承要自定义类,继承QLabel,重写三个方法
2、整体是垂直布局,按钮采用水平布局,就是说QWidget中是垂直布局,垂直布局中有个标签还有个水平布局,水平布局中有三个按钮
3、通过往垂直布局中加入addStretch可以讲按钮控制在下半部分,根据我的代码来说,按钮上面占全部大小的三份,下面站全部大小的一份,也就是3:1,按钮在从下往上的四分之一处
4、按钮信号是clicked,不再需要显示的emit发送信号,因为内部已经做了
更多推荐

所有评论(0)