Python界面设计——GUI编程之PyQt5
Posted 码字小萌新♡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python界面设计——GUI编程之PyQt5相关的知识,希望对你有一定的参考价值。
文章目录
- 一. PyQt5基础
- 二. Pycham活动模板设置
- 三. QObject
- 四. Qwidget
- 三. 常用组件
- QObject
一. PyQt5基础
🔰常用模块:
- QtWidgets:包含了一整套UI元素控件,用于建立符合系统风格的界面;
- QtGui:涵盖了多种基本图形功能的类(字体, 图形,图标,颜色);
- QtCore:涵盖了包的核心的非GUI功能(时间,文件,目录,数据类型,文本流,链接,线程进程);
(一) 窗口显示
import sys # 系统内置类
from PyQt5.Qt import * # 主要包含了我们常用的一些类,汇总到了一块
if __name__ == '__main__':
# 创建一个应用程序对象
app = QApplication(sys.argv)
# 创建一个空白控件(窗口)
window = QWidget()
# 设置窗口标题
window.setWindowTitle("计时器")
# 设置窗口尺寸
window.resize(500, 500)
# 移动窗口位置
window.move(200, 200)
# 创建label控件
label = QLabel(window)
# 为控件设置文本
label.setText("hello")
# 移动控件的位置
label.move(160, 160)
# 显示窗口
window.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束
sys.exit(app.exec_())
(二) PyQt5程序结构分析
1. 导入需要的包和模块
from PyQt5.Qt import *
import sys
2. 创建一个应用程序对象
# 创建一个应用程序对象
app = QApplication(sys.argv)
3. 控件的操作
🔰创建控件,设置控件(大小,位置,样式),事件,信号的处理
3.1 创建控件
🔰当我们创建一个控件之后,如果这个控件没有父控件,则把它当作顶层控件(窗口),系统会自动的给窗口添加一些装饰(标题栏),窗口控件具备一些特性(设置标题,图标);
# 创建一个空白控件(窗口) window = QWidget() # 设置窗口标题 window.setWindowTitle("计时器") # 设置窗口尺寸 window.resize(500, 500) # 移动窗口位置 window.move(200, 200)
3.2 设置控件
🔰控件也可以作为一个容器(承载其他的控件);
# 创建label控件 label = QLabel(window) # 为控件设置文本 label.setText("hello") # 移动控件的位置 label.move(160, 160)
3.3 展示控件
🔰刚创建好一个控件之后,(这个控件没有什么父控件),默认情况况下不会被显示,只有手动的调用show(0才可以显示;
🔰如果这个控件有父控件,那么一般情况下,父控件展示后,子控件会自动展示;# 显示窗口 window.show()
4. 应用程序的执行,进入到消息循环
🔰让整个程序开始执行,并且进入到消息循环(无限循环);
🔰检测整个程序所接受到的用户的交互信息;# 进入程序的主循环,并通过exit函数确保主循环安全结束 sys.exit(app.exec_())
(三) 窗口属性设置
属性 | 描述 |
---|---|
window.serGeometry(300, 300, 300, 200) | 前两个参数定义了move;后两个参数定义了resize |
window.move(400, 300) | 设置窗口左上顶端的坐标 |
window.resize(500, 500) | 设置窗口的宽度,高度 |
window.setWindowTitle(‘计算器’) | 设置窗口标题 |
window.setWindowIcon(QIcon(‘t1.jpg’)) | 设置窗口logo |
二. Pycham活动模板设置
🔰活动模板设置好以后,就可以快速生成所需模块;
🔰活动模板设置好以后,就可以快速生成所需模块;
(一) PyQt5的过程性代码结构模板
# 0. 导入需要的包和模块
from PyQt5.QtWidgets import *
import sys
# 1. 创建一个应用程序对象
app = QApplication(sys.argv)
# 2. 控件的操作
# 2.1 创建控件(创建窗口)
window = QWidget()
# 2.2 设置控件(窗口属性设置)
window.setWindowTitle("")
window.resize(500, 500)
# 设置内部控件
label = QLabel(window)
label.setText("")
# 2.3 展示控件
window.show()
# 3. 应用程序的执行,进入到消息循环
sys.exit(app.exec_())
(二) PyQt5的面向对象代码结构模板
🔰下面两个模板是,第一个里面导入第二个,再运行第一个;
1. 主模块代码结构模板
# 0. 导入需要的包和模块
from PyQt5.QtWidgets import *
import sys
# 导入控件设置函数所在的模块
from 模块名 import Window
# 1. 创建一个应用程序对象
app = QApplication(sys.argv)
# 2. 控件的操作
# 2.1 创建控件(创建窗口及子控件)
# 从Menu模块中导入控件
window = Window()
# 2.3 展示控件
window.show()
# 3. 应用程序的执行,进入到消息循环
sys.exit(app.exec_())
2. 控件设置模块代码结构模板
from PyQt5.QtWidgets import *
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("")
self.resize(500, 500)
self.setup_ui()
def setup_ui(self):
label = QLabel(self)
label.setText("")
# 在本模块内测试
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
三. QObject
(一) 对象名称,属性
1. API
API | 解析 |
---|---|
setObjectName("唯一名称") | 给一个Qt对象设置一个名称,当作对象的ID来使用。 |
objectName() | 获取一个Qt对象的名称。 |
setProperty("属性名称",值) | 给一个Qt对象动态的添加一个属性与值。 |
property("属性名称") | 获取一个对象的属性值。 |
dynamicPropertyNames() | 获取一个对象中所有通过setProperty()设置的属性名称。 |
2. 应用场景
🔰用于qss的ID选择器,属性选择器,方便统一设置样式。
3. 案例演示
🔰普通样式设置:
label = QLabel(self) label.setText("社会我顺哥") # 样式设置 label.setStyleSheet("font-size: 20px; color: rad;")
🔰优化样式设置:
1)新建一个.qss
后缀的样式文件,内写以下内容:组件选择器
QLabel font-size: 20px; color: rad;
表示只要是QLabel 组件,就将该样式作用在该组件上。前提是在
.py
文件里面写一下内容:# qss样式表的引入 with open("Qobject.qss", "r") as f: qApp.setStyleSheet(f.read()
2)若
.qss
样式文件是类同如下内容ID选择器
#notice font-size: 20px; color: rad;
组件ID选择器
QLabel#notice font-size: 20px; color: rad;
在
.py
文件里面如下设置# ID设置 label.setObjectName("notice")
这相当于是该组件的ID,类似于前端里面的类选择器
3)若.qss
样式表文件是类同如下内容组件属性值选择器
[notice_leve="warning"] color:yellow; border-color: yellow;
在
.py
文件里面如下设置# 属性与属性值的设置 label.setProperty("notice_leve", "warning")
该选择器的主要应用场景是:同一个属性设置不同的属性值,每种属性值对应一类样式。
(二) 父子对象的操作
1. API
🔰
setParent(parent)
: 设置父对象; 父对象只能设置一个 。# 设置父对象 obj3.setParent(obj1) # obj1 为 obj3 的父对象
🔰
parent()
: 获取父对象# 获取父对象 obj3.parent()
🔰
children()
: 获取所有直接子对象# 获取所有子对象 obj1.children()
🔰
findchild(参数1, 参数2, 参数3)
: 获取某一个指定名称和类型的子对象1)参数1: (类型: QObject; 类型元组: QPushButton, QLabel;)
2)参数2: (名称: notice; 可以省略)
3)参数3: (查找选项: [Qt.FindChildrenRecursively: 递归查找, 默认选项];[Qt.FindDirectChildrenOnly: 只查找直接子对象])🔰
findchildren(参数1, 参数2, 参数3)
: 获取某一个指定名称和类型的所有子对象; 参数作用和上一个类同# Qlabel组件统一改背景颜色 # 筛选出win_root里面的Qlabel组件子对象,遍历的所有筛选出来的子对象,进行修改 for sub_widget in win_root.findchildren(Qlabel): sub_widget.setStyleSheet("background-color: pink;")
2. 应用场景
🔰涉及到Qt对象内存管理机制;
🔰如果一个组件, 没有任何父组件, 那么就会被当成顶层组件(窗口);
🔰如果想要一个组件被包含在另一个控件内部,就需要设置父子关系;win_root = Qwidget() label1 = Qlabel() label1.setParent(win_root) 等价于 label1 = Qlabel(win_root)
(三) 信号处理
1. 信号与槽机制
1) 基本概念
🔰信号与槽是Qt中的核心机制,主要作用在于对象之间进行通讯。
🔰信号:当一个组件的状态发生改变时,向外界发出的信号。
🔰槽:一个执行某些操作的函数 / 方法。
🔰所有继承自QWidget的组件都支持“信号于槽”的机制。
2) 基本使用介绍
🔰组件内置一些信号,也可以自定义;
🔰不同组件内置额槽函数;自定义的函数 / 方法也是槽;连接方式及特性
🔰连接方式:
object.信号.connect(槽函数)
🔰一个信号可以连接多个槽函数;
🔰一个信号也可以连接多个槽函数;
🔰信号的参数可以是任何Python类型;
🔰一个槽可以监听多个信号;
2. API
🔰
widget.信号.connect(槽)
:连接信号与槽;信号
🔰
objectNameChanged(objectName)
: 对象名称发生改变时触发此信号;# 对象.objectNameChanged.connect(槽) obj.objectNameChanged.connect(obj_name_cao)
🔰
destroyed(obj)
: 对象被销毁时,触发此信号;# 对象.destroyed.connect(槽) obj.destroyed.connect(destroy_cao) del obj # 释放对象 / 销毁对象
🔰
windowTitleChanged(obj)
:当窗口标题改变时,触发该信号;window.windowTitleChanged.connect(cao)
🔰
windowIconChanged(obj)
:当窗口图标改变时,触发该信号;window.windowIconChanged.connect(cao)
🔰
obj.disconnect()
: 取消连接信号于槽;obj: 可以是组件,也可以是信号;obj.destroyed.disconnect()
🔰
widget.blockSignals(bool)
: 临时阻止指定组件所有的信号于槽的连接;obj.blockSignals(True) # 阻断连接 obj.blockSignals(False) # 回复连接
🔰
widget.signalsBlocked()
: 信号是否被阻止;obj.signalsBlocked() # 若结果是True,表示断开连接
🔰
widget.receivers("信号")
: 返回连接到信号的接收器数量;obj.receivers(obj.destroyed)
3. 应用场景
🔰监听信号,响应用户行为;
(四) 类型判定
1. API
🔰
isWidgetType()
: 判定是否为组件;obj.isWidgetType() # 若结果为True,表示是组件
🔰
inherits(父类)
: 判定是否继承于某一个父类;obj.inherits(“QWidget”) # 若结果为True,表示该对象继承自QWidget
2. 应用场景
🔰过滤筛选组件;
(五) 对象删除
🔰
obj.deleteLater()
: 删除一个对象时,也会解除它与父对象之间的关系;
🔰deleteLater() 并没有将对象立即销毁,而是向主消息循环发送一个event,下一次主消息循环收到这个event之后才会销毁对象。这样做的好处是可以在这些延迟删除的时间内完成一些操作,坏处就是内存释放会不及时。
🔰应用场景:想要移除某个对象的时候使用;
(六) 定时器
API
🔰
startTimer(ms, Qt.TimerType)
: 开启一个定时器;
会有一个返回值timer_id;
timer_id 是定时器的唯一标识;🔰
Qt.TimerType
参数:
Qt.PreciseTimer
精确定时器:尽可能保持毫秒准确;Qt.CoarseTimer
粗定时器:5%的误差间隔;Qt.VeryCoarseTimer
很粗的定时器: 只能到秒级;🔰
killTimer(timer_id)
:根据定时器id,杀死定时器;
🔰timerEvent()
:定时器执行事件;🎀简易计时器案例:
# 0. 导入需要的包和模块 from PyQt5.QtWidgets import * import sys class MyLabel(QLabel): def __init__(self, *args, **kwargs): super(MyLabel, self).__init__(*args, **kwargs) self.move(100, 100) self.setStyleSheet("font-size: 22px;") def setSec(self, sec): self.setText(str(sec)) def startMyTimer(self, ms): self.timer_id = self.startTimer(ms) def timerEvent(self, *args, **kwargs): # 获取当前的标签内容 current_sec = int(self.text()) current_sec -= 1 self.setText(str(current_sec)) if current_sec == 0: self.killTimer(self.timer_id) # 1. 创建一个应用程序对象 app = QApplication(sys.argv) # 2. 控件的操作 # 2.1 创建控件(创建窗口) window = QWidget() # 2.2 设置控件(窗口属性设置) window.setWindowTitle("QObject定时器的使用") window.resize(500, 500) # 设置内部控件 label = MyLabel(window) # 计时时间 label.setSec(5) # 计时间隔 label.startMyTimer(500) # 2.3 展示控件 window.show() # 3. 应用程序的执行,进入到消息循环 sys.exit(app.exec_())
四. Qwidget
🔰所有的可视组件的基类;
🔰是一个最简单的空白组件;
🔰组件是用户界面的最小元素。可接受各种事件;绘制在桌面上,展示给用户看;
🔰每个组件都是矩形的,它们按Z轴顺序排序;
🔰组件由其父组件和前面的组件剪切;
🔰没有父组件的组件,称之为窗口。一般会被包装一个框架;可以通过某些设置更改;
(一) 功能作用
1. 大小位置的获取
API | 解析 |
---|---|
label.x() | 获取相对于父组件的x位置,包含窗口框架 顶层组件则相对于桌面的x位置 |
label.y() | 获取相对于父组件的y位置 顶层组件则相对于桌面的y位置 |
label.pos() | x与y的组合 |
label.width() | 获取组件的宽度,不包含任何窗口框架 |
label.height() | 获取组件的高度,不包含任何窗口框架 |
label.size() | width和height的组合 |
label.geometry() | 获取用户区域相对于父控件的位置和尺寸大小 |
label.rect() | 0, 0, width, height 的组合 |
label.frameSize() | 获取框架大小 |
label.frameGeometry() | 获取框架位置和大小 |
2. 大小位置的设置
API | 解析 |
---|---|
label.move(x, y) | 设置组件相对于父组件的位置 顶层组件则相对于桌面的位置 |
label.resize(width, height) | 设置组件的宽和高,不包括窗口框架 |
label.setGeometry(x, y, width, height) | 设置组件的位置和大小 |
label.adjustSize() | 根据内容自适应大小 |
label.setFixedSize(width, height) | 设置固定大小 |
3. 最大和最小大小的获取
API | 解析 |
---|---|
label.minimumWidth() | 获取最小大小的宽度 |
label.minimumHeight() | 获取最小大小的高度 |
label.minimumSize() | 获取最小大小的宽度和高度 |
label.maximumWidth() | 获取最大大小的宽度 |
label.maximumHeight() | 获取最大大小的高度 |
label.maximumSize() | 获取最大大小的宽度和高度 |
4. 最大和最小大小的设置
API | 解析 |
---|---|
label.setMaximumWidth(MaxWidth) | 设置最大大小的宽度 |
label.setMaximumHeight(MaxHeight) | 设置最大大小的高度 |
label.setMaximumSize(MaxWidth, MaxHeight) | 设置最大大小的宽度和高度 |
label.setMinimumWidth(MinWidth) | 设置最小大小的宽度 |
label.setMinimumHeight(MinHeight) | 设置最小大小的高度 |
label.setMinimumSize(MinWidth, MinHeight) | 设置最小大小的宽度和高度 |
5. 内容边距
🔰调整组件内容边距,使得显示更好看;
API 解析 label.setCOntentsMargins(左,上,右,下)
设置内容边距 label.getContentsMargins()
获取内容边距 label.contentsRect()
获取内容边距
6. 鼠标相关操作
1)设置鼠标形状
🔰
label.setCursor(参数)
该API的参数如下:
参数 显示效果 Qt.ArrowCursor Qt.UpArrowCursor Qt.CrossCursor Qt.IBeamCursor Qt.WaitCursor Qt.BusyCursor Qt.ForbiddenCursor Qt.PointingHandCursor Qt.WhatsThisCursor Qt.SizeVerCursor Qt.SizeHorCursor Qt.SizeBDiagCursor Qt.SizeAllCursor Qt.SplitHCursor Qt.SplitVCursor Qt.OpenHandCursor Qt.ClosedHandCursor Qt.BlankCursor QCursor对象 自定义鼠标形状 window.unsetCursor()
重置鼠标形状 window.cursor() 获取鼠标 自定义鼠标
pixmap = QPixmap("qq.jpg") # 图片对象 new_pixmap = pixmap.scaled(50, 50) # 图片大小 cursor = QCursor(new_pixmap, 0, 0) # 鼠标对象,及作用点坐标位置 window.setCursor(cursor)
2)鼠标跟踪
🔰
window.hasMouseTracking()
:判定是否设置了鼠标跟踪;
🔰window.setMouseTracking(True)
:设置鼠标是否跟踪;
🔰所谓的鼠标跟踪,其实就是设置检测鼠标移动事件的条件;
🔰不跟踪:鼠标移动时,必须处于按下状态,才会触发mouseMoveEvent事件;
🔰跟踪:鼠标移动时,不处于按下状态,也会触发mouseMoveEvent事件;
7. 事件
🔰当一个组件被触发了一个特定的行为时,就会调用特定的方法,来将事件传递给开发人员,方便处理;
🔰重写这些事件方法,就可以监听相关的信息;
1)监听显示和关闭事件
API | 解析 |
---|---|
def showEvent(self, QShowEvent): | 该事件在组件显示时触发 |
def closeEvent(self, QCloseEvent): | 该事件在组件关闭时触发 |
2)监听移动事件
API | 解析 |
---|---|
def moveEvent(self, QMoveEvent): | 该事件在组件移动时触发 |
3)监听调整大小事件
API | 解析 |
---|---|
def resizeEvent(self, QResizeEvent): | 该事件在组件大小被调整时触发 |
4)监听鼠标事件
API | 解析 |
---|---|
def enterEvent(self, QEvent): | 该事件在鼠标进入组件范围时触发 |
def leaveEvent(self, QEvent): | 该事件在鼠标离开组件范围时触发 |
def mousePressEvent(self, QMouseEvent): | 该事件在鼠标按下时触发 |
def mouseReleaseEvent(self, QMouseEvent): | 该事件在鼠标释放时触发 |
def mouseDoubleClickEvent(self, QMouseEvent): | 该事件在鼠标双击时触发 |
def mouseMoveEvent(self, QMouseEvent): | 该事件在鼠标按下后移动时触发 |
def mouseMoveEvent(self, QMouseEvent): ___ self.setMouseTracking(True) 追踪设置 | 追踪设置后,没有按下的移动也能触发 |
5)监听键盘事件
API | 解析 |
---|---|
def keyPressEvent(self, QKeyEvent): | 该事件在键盘按下时触发 |
def keyReleaseEvent(self, QKeyEvent): | 该事件在键盘释放时触发 |
🔰修饰键:
Qt.NoModifier
:没有修饰键;Qt.ShiftModifier
:Shift 键被按下;Qt.ControlModifier
:Ctrl 键被按下;Qt.AltModifier
:Alt 键被按下;
多个修饰键之间使用或运算;🔰普通键:
Qt.Key_xxx
🔰实例:创建一个窗口,用户区支持拖拽。鼠标点击了用户区拖拽也可以移动窗口;
from PyQt5.QtCore import Qt from PyQt5.QtWidgets import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("用户区鼠标拖拽窗口") self.resize(500, 500) # 鼠标按下时,触
开源分享基于Python+OpenCV+PyQt5车牌识别(GUI界面)
亲测无错:基于Python+OpenCV+PyQt5车牌识别(GUI界面)绝对可以用的!!!!!
基于Python+OpenCV+PyQt5车牌识别(GUI界面)
参考文档
以上是关于Python界面设计——GUI编程之PyQt5的主要内容,如果未能解决你的问题,请参考以下文章