PyQt5 基本语法(一):基类控件
基类控件
一、 简介
1、 什么是 Qt
使用 C++ 语言编写的跨平台 GUI 库,支持Windows 、MacOS和Linux。由于 Qt 使用C++语言编写,所以使用Qt开发的GUI程序的界面风格与当前操作系统完全相同,而且运行效率很高
2、 什么是PyQt
PyQt实现了一个Python模块集。它有超过300类,将近6000个函数和方法。它是一个多平台的工具包,可以运行在所有主要操作系统上,包括UNIX,Windows和Mac。 PyQt采用双许可证,开发人员可以选择GPL和商业许可。在此之前,GPL的版本只能用在Unix上,从PyQt的版本4开始,GPL许可证可用于所有支持的平台 ,同时Qt能实现的功能PyQt都能实现
3、 环境搭建
安装 PyQt5
pip install pyqt5
官方文档:【https://www.riverbankcomputing.com/static/Docs/PyQt5/sip-classes.html】
二、 基本结构
1、 第一个程序
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun # @file: Demo.py # @time: 2022/3/28 9:20 from PyQt5.QtWidgets import QApplication, QWidget, QLabel, qApp import sys # 创建一个应用程序 # sys.argv 当别人通过命令行执行这个程序的时候,可以设定一种功能(接收命令行传递的参数) app = QApplication(sys.argv) print(app.arguments()) # 得到命令行的参数 print(qApp.arguments()) # qApp为全局变量 # 创建一个窗口 w = QWidget() # 窗口尺寸 w.resize(300, 150) # 移动窗口,窗口左上角的坐标 w.move(300, 300) # 设置窗口的标题 w.setWindowTitle("第一个基于pyqt5的桌面应用") # 设置标签 label = QLabel(w) label.setText("hello world") label.move(150, 75) # 显示窗口 w.show() # 进入程序的消息循环,并通过exit函数确保主循环安全结束,相当于无限循环 # 检测整个程序所接收到的用户交互信息 sys.exit(app.exec_())
2、 控件操作
步骤:
-
创建控件
-
# 设置标签 label = QLabel(contain) 参数:
- contain:代表要在哪个控件(容器)上面展示,可以为空
当我们创建一个控件之后,如果说,这个控件没有父控件,则把它当作顶层控件(窗口)
-
-
设置控件
- 大小,样式,位置,样式等
- 顶层控件有权限去设置窗口内容,结构等
-
展示控件
- 当控件没有父控件时,要使用 show 方法去展示控件
3、 快速生成代码
在pycharm中的活动模板配置如下代码,快速生成代码
from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("$test$") # 设置标题 self.resize($500$, $500$) # 设置窗口大小 self.move($300$, $300$) # 移动窗口 self.setup_ui() # 调用创建控件的方法 def setup_ui(self): # 添加控件的操作 pass if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
4、 面向对象
提高代码的可维护性
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun # @file: Demo.py # @time: 2022/3/28 9:20 from PyQt5.QtWidgets import QApplication, QWidget, QLabel class Window(QWidget): def __init__(self): super(Window, self).__init__() self.setWindowTitle("Hello") # 设置标题 self.resize(300, 150) # 设置窗口大小 self.move(300, 300) # 移动窗口 self.setup_label() # 调用创建控件的方法 def setup_label(self): # 添加控件的操作 label = QLabel(self) label.setText("Hello World") label.move(150, 75) if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
三、 基类控件
什么是控件?
- 一个程序界面上的各个独立的标准,一块矩形区域
- 每类控件都具备不同的功能
- 同时,有些控件有相似的功能,可以通过继承关系学习
1、 QObject
1.1 设置标识
1.1.1 语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun # @file: Demo.py # @time: 2022/3/28 9:20 from PyQt5.Qt import * obj = QObject(self) obj.setObjectName("notice") # 设置Qt对象名称 print(obj.objectName()) # 获得Qt对象名称 obj.setProperty("notice_l", "error") # 设置对象的属性 obj.setProperty("notice_l2", "warning") print(obj.property("notice_l")) # 获得一个对象的属性值 print(obj.dynamicPropertyNames()) # 获取一个对象中所有通过setProperty设置的属性名称
1.1.2 应用场景
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun # @file: Demo.py # @time: 2022/3/28 9:20 from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QObject") # 设置标题 self.resize(500, 300) # 设置窗口大小 self.move(500, 500) # 移动窗口 self.setup_ui() # 调用创建控件的方法 def setup_ui(self): # 添加控件的操作 self.qObject_ui() def qObject_ui(self): # 所有类的基类 # 案例演示 label = QLabel(self) # 创建标签 label.setText("Hello") # 设置标签内容 label.setObjectName("notice") # id 为 notice label.setProperty("level", "error") # 属性选择器 with open("QStyle.qss", "r") as f: """ 文件内容为: QLabel#notice[level='error'] { font-size: 20px; color: blue; } """ qApp.setStyleSheet(f.read()) # label.setStyleSheet("font-size: 20px; color: blue;") # qss 样式表,相当于前端的 css 样式表,可以将其放入一个 `.qss` 的文件中,方便分离和读取,同时,所有符合条件的内容都会变成相应的样式 if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
1.3 父子对象
1.3.1 语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * obj1 = QObject() obj2 = QObject() obj3 = QObject() obj2.setParent(obj1) # 设置父子关系 obj3.setObjectName("2") # 设置id obj3.setParent(obj2) print(obj1, obj2.parent()) # 获取父类,返回内存地址 print(obj2, obj1.children()) # 获取所有直系子对象 print(obj1.findChild(QObject)) # 获取后代,递归查找,只返回一个 print(obj1.findChild(QObject, "2")) # 获取id为2的后代,只返回一个 print(obj1.findChildren(QObject)) # 获取符合条件的所有后代
1.3.2 应用场景
内存管理机制,父控件删除,那么子控件也会自动删除
- 按钮和对话框本身是父子控件关系
- 当对话框被删除时,内部的子控件也会自动删除——非常合理
- 我们操作的时候,是操作的对话框控件本身,而不是内部的子控件
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * obj1 = QObject() obj2 = QObject() obj1.setParent(obj2) # 监听 obj2 对象被释放 obj2.destroyed.connect(lambda: print("obj2,被释放")) print("删除父对象") del obj1 print("删除完成")
如果一个控件,没有任何父控件,那么就会被当成顶层控件——多个顶层窗口相互独立
如果想要一个控件被包含在另外一个控件内部,就需要设置父子关系
- 显示位置受父控件约束
- 生命周期也被符对象接管
案例:
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) win1 = QWidget() win1.setStyleSheet("background-color: blue;") win1.setWindowTitle("blue") win1.resize(500, 500) win1.show() win2 = QWidget(win1) win2.setStyleSheet("background-color: red;") win2.setWindowTitle("red") win2.resize(100, 100) # win2.setParent(win1) # win1 为父对象,win2 = QWidget(win1) 效果一样 win2.show() l1 = QLabel() b1 = QPushButton() l1.setParent(win1) b1.setParent(win1) l1.setText("label") b1.setText("button") l1.move(200, 200) b1.move(300, 200) l2 = QLabel() l2.setParent(win1) l2.setText("Label") l2.move(100, 200) # 遍历设置样式 for i in win1.findChildren(QLabel): i.setStyleSheet("color: green;") l1.show() b1.show() l2.show() sys.exit(app.exec_())
1.4 信号操作
1.4.1 信号与槽机制
信号和槽是Qt中的核心机制,主要作用在于对象之间进行通讯
- 当达到某个条件时,执行某个操作
信号(widget):
- 当一个控件的状态发生改变时,向外发出信息
槽(connect):
- 一个执行某些操作的函数/方法
所有继承自 QWidget 的控件都支持信号与槽机制
1.4.2 机制描述
手动操作:
- 信号和槽相关联
自动操作:
- 当信号发出时,连接槽函数会自动执行
1.4.3 信号处理
信号:
objectNameChange(objectName)
:对象名称发生改变时,发射此信号destroyed(obj)
:对象被销毁时,发射信号blockSignals(True)
:临时阻断连接receivers(widget)
:查看当前信号连接了多少个槽
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * def destroy(): print("对象被摧毁") obj1 = QObject() obj2 = QObject() obj1.setParent(obj2) # obj.destroyed obj1.destroyed.connect(lambda: destroy()) # obj.objectNameChanged obj1.objectNameChanged.connect(lambda name: print("对象名称被改变: " + name)) obj1.setObjectName("xxx") # obj1.objectNameChanged.disconnect() # 断开槽与信号的连接 obj1.blockSignals(True) # 临时阻断连接 obj1.setObjectName("1") print("连接数量:" + str(obj1.receivers(obj1.objectNameChanged))) # 查看有多少个槽连接这个信号 obj1.blockSignals(False) # 再次开启连接 obj1.objectNameChanged.connect(lambda name: print("第二个连接:" + name)) print("连接数量:" + str(obj1.receivers(obj1.objectNameChanged))) # 查看有多少个槽连接这个信号 obj1.setObjectName("2") del obj2
1.4.4 案例
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("test") # 设置标题 self.resize(300, 300) # 设置窗口大小 self.move(200, 300) # 移动窗口 self.setup_ui() # 调用创建控件的方法 def ret(): print("标题变化了") # self.windowTitleChanged.disconnect() # 断开槽与信号的关系 self.blockSignals(True) # 临时断开连接也行 self.windowTitleChanged.connect(ret) def setup_ui(self): # 添加控件的操作 self.btn() # 添加按钮 def btn(self): b = QPushButton(self) b.setText("点击我") def ret(): self.setWindowTitle("hello") b.clicked.connect(ret) if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
1.5 类型判定
1.5.1 语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() obj = QObject(w) w1 = QWidget(w) l = QLabel(w) print(w.isWidgetType()) # 判断是继承控件类型 print(obj.isWidgetType()) # 判断是否继承控件类型 print(l.isWidgetType()) # 判断是否继承控件类型 print(w.inherits("QWidget")) # 判断是否继承控件类型 print(obj.inherits("QLabel")) # 判断是否继承标签类型 print(l.inherits("QLabel")) # 判断是否继承标签类型 sys.exit(app.exec_())
1.5.2 案例
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("test") # 设置标题 self.resize(500, 500) # 设置窗口大小 self.move(300, 300) # 移动窗口 self.setup_ui() # 调用创建控件的方法 def setup_ui(self): # 添加控件的操作 l = QLabel(self) l.setText("first") l.move(100, 100) l2 = QLabel(self) l2.setText("second") l2.move(200, 100) btn = QPushButton(self) btn.setText("点我") btn.move(300, 100) for i in self.findChildren(QWidget): if i.inherits("QLabel"): # 如果为 label 类型,修改样式 i.setStyleSheet("color: red; font-size: 20px") else: i.setStyleSheet("color: blue; font-size: 20px") if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
1.6 对象删除
1.6.1 语法
删除一个对象时,也会解除它与父对象之间的关系
obj.deleteLater()
:其并没有将对象立即销毁,而是向主消息循环发送了一个event,下一次主消息循环收到这个event之后才会销毁对象- 这样做的好处是可以在这些延迟删除的时间里面完成一些操作;坏处是内存释放会不及时
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() obj1 = QObject() obj2 = QObject() obj3 = QObject() obj3.setParent(obj2) obj2.setParent(obj1) obj1.destroyed.connect(lambda: print("obj1被释放")) obj2.destroyed.connect(lambda: print("obj2被释放")) obj3.destroyed.connect(lambda: print("obj3被释放")) # obj1.deleteLater() obj2.deleteLater() # 等下一个循环开始时才会真正释放 # del obj2 # 直接删除,但是这是把变量和对象的关联替换了,使得系统无法访问对象,不是真的删除 print(obj1) w.show() sys.exit(app.exec_())
1.7 事件处理
信号与槽机制是对事件机制的高级封装
事件机制更偏离底层
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class App(QApplication): def notify(self, rev, evt): if rev.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress: # 过滤器,只查看按钮事件,并且只查看鼠标点击事件 print("底层运行原理:") print(rev, evt) return super().notify(rev, evt) # 分发事件 class Btn(QPushButton): def event(self, evt): if evt.type() == QEvent.MouseButtonPress: # 事件过滤 print("按钮点击了", evt) # 里面很多事件 return super().event(evt) def mousePressEvent(self, evt): print("鼠标被点击了。。。。。。。。。。") # 如果只有这行代码的话,没有运行信号与槽的操作 return super().mousePressEvent(evt) app = App(sys.argv) w = QWidget() btn = Btn(w) btn.setText("按钮") btn.move(100, 100) btn.pressed.connect(lambda: print("按钮被按下")) btn.clicked.connect(lambda: print("按钮被点击")) btn.released.connect(lambda: print("按钮被松开")) w.show() sys.exit(app.exec_())
1.8 定时器操作
1.8.1 语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class MyObject(QObject): def timerEvent(self, evt): print(evt, "1") # 每个1秒打印 return super().timerEvent(evt) app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("定时器") w.resize(500, 500) obj = MyObject() t_id = obj.startTimer(1000) # 1秒执行一次,通过继承的方法来启动计时器 obj.killTimer(t_id) # 关闭定时器 w.show() sys.exit(app.exec_())
1.8.2 应用场景
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class MyLabel(QLabel): def __init__(self, sec, *args, **kwargs): # 使用不定长参数传参 super().__init__(*args, **kwargs) self.move(20, 20) self.setText(sec) self.setStyleSheet("font-size: 20px; color: red;") self.t_id = self.startTimer(1000) # 1秒执行一次,通过继承的方法来启动计时器 def timerEvent(self, evt): # 倒计时原理 sec = int(self.text()) sec -= 1 self.setText(str(sec)) if (sec == 0): self.killTimer(self.t_id) # 关闭定时器 class MyQWidget(QWidget): def __init__(self, *args, **kwargs): super(MyQWidget, self).__init__(*args, **kwargs) self.setWindowTitle("定时器") self.resize(500, 500) self.startTimer(1000) # 动画 def timerEvent(self, evt): current_w, current_h = self.width(), self.height() if current_w > 1000 and current_h > 1000: current_w -= 20 current_h -= 20 elif current_h < 1000 and current_w < 1000: current_w += 20 current_h += 20 self.resize(current_w, current_h) app = QApplication(sys.argv) w = MyQWidget() MyLabel("10", w) # 同时,10秒倒计时 w.show() sys.exit(app.exec_())
2、 QWidget
2.1 简介
介绍
-
其为所有可视控件的基类
-
是一个最简单的空白控件
-
控件是用户界面的最小元素
- 接收各种事件(鼠标、键盘等)
- 绘制在桌面上面,展示给用户看
-
每个控件都是矩形的,它们按Z轴顺序排序
-
控件由其父控件和前面的控件剪切
-
没有父控件的控件称之为窗口
2.2 继承
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * print(QWidget.__bases__) # 直系父类 print(QWidget.mro()) # 所有父类,祖宗类
父类几乎所有的方法,子类都可以使用
2.3 控件创建
语法:
w = QWidget(parent) # 如果没有父类,可以不用填写
2.4 大小位置
2.4.1 获取
控件的坐标系统:
- 以左上角为坐标原点,纵轴为垂直方向,横轴为水平方向
获取位置:
(x(), y()) / pos()
:- 相对于父控件的位置,包含窗口框架;顶层控件则相对于桌面的位置
QPoint(x, y)
(width(), height()) / size()
:- 控件的宽度和高度,不包含窗口框架
QSize(width, height)
geometry()
:- 用户区域相对于父控件的位置和尺寸的组合,不包含窗口框架
QRect(x, y, width, height)
rect()
:- 控件尺寸的组合,不包含窗口框架
QRect(0, 0, width, height)
frameSize()
:- 框架大小
frameGeometry()
:- 框架位置和尺寸
- 注意:
- 控件显示完毕之后,具体位置或者尺寸数据才会正确
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.move(100, 100) w.resize(200, 200) w.show() # 桌面显示后获取的数据才准确 print(w.x()) print(w.width()) print(w.geometry()) print(w.rect()) print(w.frameSize()) print(w.frameGeometry()) sys.exit(app.exec_())
2.4.2 设置
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ move(x, y) 操作的是 x, y 也就是 pos,包含窗口框架 resize(width, height) 操作的是宽高:不包含窗口框架 setGeometry(x_noFrame, y_noFrame, width, height) 此处参照为用户区域,即不包含框架 adjustSize() 根据内容自适应大小 setFixedSize() 设置固定尺寸 """ app = QApplication(sys.argv) w = QWidget() """ w.move(100, 100) w.resize(200, 200) # 下面这行代码和上面两行代码的作用类似 w.setGeometry(100, 100, 200, 200) """ w.setFixedSize(500, 500) # 不可以修改它的大小 w.show() sys.exit(app.exec_())
2.5 尺寸最值
2.5.1 获取
获取:
(minimumWidth(), minimumHeight()) / minimumSize()
- 最小尺寸
(maximumWidth(), msximumHeight()) / maximumSize()
- 最大尺寸
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) w.show() print(w.minimumSize()) # 得到最小尺寸 print(w.maximumSize()) # 得到最大尺寸 sys.exit(app.exec_())
2.5.2 设置
设置最大最小尺寸
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) w.setMaximumWidth(1000) # 限定最大宽度 w.setMaximumHeight(1000) # 限定最大高度 w.setMaximumSize(1000, 1000) # 限定最大宽度和高度 w.setMinimumSize(100, 100) # 限定最小宽度和高度 w.setMinimumWidth(100) # 限定最小宽度 w.setMinimumHeight(100) # 限定最小高度 w.show() sys.exit(app.exec_())
限定最值尺寸后,如果修改后的尺寸超过这个最值,最终大小为最值大小
2.6 内容边距
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) l = QLabel(w) l.setText("Hello World") l.setStyleSheet("background-color: red; font-size: 20px; font-weight: 500;") l.resize(300, 300) l.setContentsMargins(110, 0, 0, 0) # 设置内容外边距 print(l.contentsRect().getRect()) # 得到内容区域 print(l.getContentsMargins()) # 得到内容外边距 w.show() sys.exit(app.exec_())
必须是控件本身有足够空间
2.7 鼠标相关
2.7.1 设置鼠标形状
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) pixmap = QPixmap(r"D:\35005\Pictures\Screenshots\微信图片_20220302175157.jpg") # 传入图片设置鼠标图标 pixmap_new = pixmap.scaled(50, 50) # 输入缩放的尺寸 cursor = QCursor(pixmap_new) # 实例化鼠标对象 # w.setCursor(Qt.BusyCursor) # 设置鼠标形状,参数里面输入鼠标样式 w.setCursor(cursor, 0, 0) # 也可以传入一个鼠标对象,后面的数字传入的意思是以左上角为标准 w.unsetCursor() # 取消设置鼠标的形状 w.show() sys.exit(app.exec_())
常见的鼠标样式查询:https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtcore/qt.html#CursorShape
如果鼠标进入了控件的范围内,形状发生变化
2.7.2 重置鼠标形状
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) current_cursor = w.cursor() # 获取鼠标对象 print(current_cursor.pos()) # 获得鼠标相对于电脑屏幕的位置坐标 current_cursor.setPos(10, 10) # 设置鼠标的位置 w.show() sys.exit(app.exec_())
2.7.3 鼠标跟踪
所谓的鼠标跟踪,其实就是设置检测鼠标移动事件的条件
鼠标跟踪:
- 鼠标移动时,不处于按下状态,也会触发 mouseMoveEvent 事件
鼠标不跟踪:
- 鼠标移动时,必须处于按下状态,才会触发 mouseMoveEvent 事件
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class MyWidget(QWidget): def mouseMoveEvent(self, me): print("鼠标移动了", me.localPos()) # 当不跟踪时,鼠标要按下才会触发 # me.pos()和 me.localPos() 得到鼠标相对于控件的位置 app = QApplication(sys.argv) w = MyWidget() w.setWindowTitle("鼠标事件") w.resize(500, 500) w.setMouseTracking(True) # 开启鼠标跟踪 print(w.hasMouseTracking()) # 判定是否开启鼠标跟踪 w.show() sys.exit(app.exec_())
2.7.4 案例
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys # 鼠标按下移动标签 class MyWidget(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.resize(500, 500) self.setWindowTitle("鼠标事件案例") self.label = QLabel(self) self.setup_ui() def mouseMoveEvent(self, me): x, y = me.x(), me.y() self.label.move(x, y) def setup_ui(self): self.label.resize(100, 100) self.label.setText("按住我!") self.label.setStyleSheet("background-color: green; font-weight: bold;") if __name__ == '__main__': app = QApplication(sys.argv) w = MyWidget() w.show() sys.exit(app.exec_())
2.8 事件
2.8.1 API
显示和关闭事件:
showEvent(QShowEvent) # 控件显示是调用 closeEvent(QCloseEvent) # 控件关闭时调用
移动事件:
moveEvent(QMoveEvent) # 控件移动时调用
调整大小事件:
resizeEvent(QResizeEvent) # 控件大小改变时调用
鼠标事件:
enterEvent(QEvent) # 鼠标进入时触发 leaveEvent(QEvent) # 鼠标离开时触发 mousePressEvent(QMouseEvent) # 鼠标按下时触发 mouseReleaseEvent(QMouseEvent) # 鼠标按下时触发 mouseDoubleClickEvent(QMouseEvent) # 鼠标双击时触发 mouseMoveEvent(QMouseEvent) # 鼠标按下后移动时触发,设置追踪后,没按下也能触发
键盘事件:
keyPressEvent(QKeyEvent) # 键盘按下时使用 keyReleaseEvent(QKeyEvent) # 键盘松开时使用
焦点事件:
focusInEvent(QFocusEvent) # 获得焦点 focuseOutEvent(QFocusEvent) # 失去焦点
拖拽事件:
dragEnterEvent(QDragEnterEvent) # 拖拽进入控件时使用 dragLeaveEvent(QDragLeaveEvent) # 拖拽离开控件时使用 dragMoveEvent(QDragMoveEvent) # 拖拽在控件内移动时使用 dropEvent(QDropEvent) # 拖拽放下时使用
绘制事件:
paintEvent(QPaintEvent) # 显示控件,更新控件时使用
改变事件:
changeEvent(QEvent) # 窗体改变,字体改变时调用
右键菜单:
contextMenuEvent(QContextMenuEvent) # 访问右键菜单时使用
输入法:
inputMethodEvent(QInputMethodEvent) # 输入法切换调用
当一个控件被触发了一个特定的行为时,就会调用特定的方法,来将事件传递给开发人员,方便处理
重写事件方法,就可以监听相关的信息
2.8.2 示例
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("test") # 设置标题 self.resize(500, 500) # 设置窗口大小 self.move(100, 100) # 移动窗口 def showEvent(self, ev): print("窗口被展示了出来", ev) def closeEvent(self, ev): print("窗口关闭", ev) def moveEvent(self, ev): print("窗口移动", ev.pos()) def resizeEvent(self, ev): print("控件大小改变", ev.size()) def enterEvent(self, ev): print("鼠标进入了", ev) def leaveEvent(self, ev): print("鼠标离开了", ev) def mousePressEvent(self, ev): print("鼠标按下了", ev.button()) def mouseReleaseEvent(self, ev): print("鼠标松开", ev) def mouseDoubleClickEvent(self, ev): print("鼠标双击了", ev.flags()) def mouseMoveEvent(self, ev): print("鼠标在移动", ev) def keyPressEvent(self, ev): print("键盘按下了:", chr(ev.key())) def keyReleaseEvent(self, ev): print("键盘松开了:", chr(ev.key())) def focusInEvent(self, ev): print("获得焦点") def focusOutEvent(self, ev): print("失去焦点") if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
2.8.3 事件传递
如果一个控件没有处理该事件,则会自动传递给父控件进行处理
事件对象具有两种特殊方法:
accept()
:- 自己处理这个事件,并告诉系统不要在向上层传递
ignore()
:- 自己忽略这个事件,但是会执行;告诉系统,继续往后传递
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class Window(QWidget): def mousePressEvent(self, ev): print("顶层鼠标按下") class MidWindow(QWidget): def mousePressEvent(self, ev): ev.ignore() # 转发给父对象,但是也会接收对象 print(ev.isAccepted()) print("中间鼠标按下") class Label(QLabel): def mousePressEvent(self, ev): print("标签控件鼠标按下") ev.accept() # 不用转发给父对象,接收对象 print(ev.isAccepted()) app = QApplication(sys.argv) w = Window() w.setWindowTitle("事件转发") w.resize(500, 500) m_w = MidWindow(w) m_w.resize(300, 300) m_w.setAttribute(Qt.WA_StyledBackground, True) m_w.setStyleSheet("background-color: yellow;") label = Label(m_w) label.setText("这是一个标签") label.setStyleSheet("background-color: skyblue;") label.move(110, 110) # 注意这个底层事件会被顶层事件覆盖 w.show() sys.exit(app.exec_())
2.8.4 案例
-
创建一个窗口包含一个标签
- 鼠标进入标签时,展示欢迎光临
- 鼠标离开标签时,展示谢谢惠顾
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class Label(QLabel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.resize(200, 200) self.move(100, 100) self.setStyleSheet("background-color: skyblue;") def enterEvent(self, *args, **kwargs): self.setText("欢迎光临") def leaveEvent(self, *args, **kwargs): self.setText("谢谢惠顾") app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("鼠标操作案例1") w.resize(500, 500) label = Label(w) w.show() sys.exit(app.exec_()) -
创建一个窗口,监听用户按键
- 监听用户输入Tab键
- 监听用户输入Ctrl + S 组合键
- 监听用户输入Ctrl + Shift + v 组合键
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys class Label(QLabel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.resize(200, 200) self.move(100, 100) self.setStyleSheet("background-color: skyblue; font-weight: 500;") self.grabKeyboard() # 捕获键盘事件 # self.releaseKeyborad() # 停止捕获键盘事件 def keyPressEvent(self, ev): # 监听 Tab 键 if ev.key() == Qt.Key_Tab: # 监听普通键 self.setText('用户点击的是Tab键') # 监听 Ctrl + C 修饰键 Ctrl 并且 普通键 C Qt.AltModifier:其为 Alt 组合键 if ev.modifiers() == Qt.ControlModifier and ev.key() == Qt.Key_C: self.setText("正在复制文本内容") # 监听 Ctrl + Shift + v 修饰键 Ctrl + Shift (使用按位或组合获取) 并且普通键 V if ev.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and ev.key() == Qt.Key_V: self.setText("正在粘贴内容") app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("鼠标操作案例1") w.resize(500, 500) label = Label(w) w.show() sys.exit(app.exec_()) -
完成窗口,用户区支持拖拽
- 确定鼠标移动的距离(向量 x, y)
- 原始窗口坐标点 + 向量
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * class Window(QWidget): def __init__(self): super().__init__() self.move_flag = False # 判断是否在移动 self.setWindowTitle("内容拖动") # 设置标题 self.resize(500, 500) # 设置窗口大小 self.move(100, 100) # 移动窗口 self.mouse = () # 移动前的坐标 self.origin = () # 原始的坐标 def mousePressEvent(self, evt): """ print(evt.localPos()) # 得到是相对于窗口左上角的坐标 print(evt.globalPos()) # 得到的是相对于电脑左上角的坐标 """ if evt.button() == Qt.LeftButton: self.move_flag = True # 设定标记 self.mouse = (evt.globalX(), evt.globalY()) self.origin = (self.x(), self.y()) # 左上角坐标 def mouseMoveEvent(self, evt): if self.move_flag: # 相对移动 move_x = evt.globalX() - self.mouse[0] move_y = evt.globalY() - self.mouse[1] self.move(self.origin[0] + move_x, self.origin[1] + move_y) def mouseReleaseEvent(self, evt): # 确定最终位置 self.move_flag = False if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
2.9 父子关系
2.9.1 语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("父子关系") w.resize(500, 500) l1 = QLabel(w) l1.setText("标签1") l2 = QLabel(w) l2.setText("标签2") l2.move(50, 0) l3 = QLabel(w) l3.setText("标签3") l3.move(100, 0) print(w.childAt(50, 0)) # 获得对应坐标的子控件 print(l2.parentWidget()) # 获得父控件 print(w.childrenRect().getRect()) # 打印子控件所占有的矩形区域 w.show() sys.exit(app.exec_())
2.9.2 案例
创建窗口,若干个Label控件,实现点击功能
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys # class MyLabel(QLabel): # 借助子控件 # def mousePressEvent(self, evt): # for i in self.parentWidget().findChildren(MyLabel): # 获取父控件 # i.setStyleSheet("") # self.setStyleSheet("background-color: red;") class MyWidget(QWidget): def mousePressEvent(self, evt): subLabel = self.childAt(evt.x(), evt.y()) if subLabel: # 如果点击了标签;避免了报错 for i in self.findChildren(QLabel): # 获取所有子控件,并清空样式 i.setStyleSheet("") subLabel.setStyleSheet("background-color: red;") # 给制定内容修改样式 app = QApplication(sys.argv) w = MyWidget() w.setWindowTitle("父子关系") w.resize(500, 500) for i in range(11): l = QLabel(w) l.setText(f"标签{i}") l.move(50 * i, 50 * i) w.show() sys.exit(app.exec_())
2.10 层级控制
高层级控件会被低层级控件覆盖
语法:
lower() # 将控件层级降低到最底层 raise_() # 将控件提升到最上层 a.stzckUnder(b) # 让 a 放在 b 下面
注意:以上操作专指同级顺序
应用:需要调整控件Z轴顺序
2.11 顶层窗口
2.11.1 基本语法
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() icon = QIcon(r"D:\35005\Pictures\Screenshots\微信图片_20220302175157.jpg") # 创建图标对象 w.setWindowIcon(icon) # 设置窗口图标 print(w.windowIcon()) # 获取图标对象 w.setWindowTitle("Hello") # 默认为 python print(w.windowTitle()) # 获取窗口的标题 w.setWindowOpacity(0.9) # 设置不透明度,范围是 0 ~ 1 print(w.windowOpacity()) # 获取窗口不透明度 w.setWindowState(Qt.WindowActive) # 设置窗口状态,有 无状态(WindowNoSate) 最小化(WindowMinimized) # 最大化(WindowMaximized) 全屏(WindowFullScreen) 活动窗口(WindowActive) print(w.windowState()) # 获取窗口状态 w.show() sys.exit(app.exec_())
2.11.2 最大化和最小化
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() # w.showMaximized() # 最大化展示 # w.showMinimized() # 最小化展示 # w.showNormal() # 正常展示 # w.showFullScreen() # 全屏展示 print(w.isMinimized()) # 查看是否为最小化 print(w.isMaximized()) # 查看是否为最大化 print(w.isFullScreen()) # 查看是否为全屏 w.show() sys.exit(app.exec_())
2.11.3 窗口标志
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.setWindowFlags(Qt.WindowStaysOnTopHint) # 设置顶层窗口的外观标志 w.show() sys.exit(app.exec_())
属性 描述 Qt.MSWindowsFixedSizeDialogHint 固定窗口,无法调整大小 Qt.FramelessWindowHint 窗口无边框 Qt.CustomizeWindowHint 有边框,无标题栏与按钮,不能移动和拖动 Qt.WindowTitleHint 添加标题栏与关闭按钮 Qt.WindowSystemMenuHint 添加系统目录和关闭按钮 Qt.WindowMaximizeButtonHint 激活最大化按钮与关闭按钮,禁止最小化按钮 Qt.WindowMinimizeButtonHint 激活最小化按钮与关闭按钮,禁止最大化按钮 Qt.WindowMinMaxButtonsHint 激活最大化与最小化按钮和关闭按钮 Qt.WindowCloseButtonHint 添加一个关闭按钮 Qt.WindowContextHelpButtonHint 添加问号与关闭按钮,像对话框一样 Qt.WindowStaysOnTopHint 窗口始终处于顶部位置 Qt.windowStaysOnButtonHint 窗口始终处于底部位置
2.11.4 案例
创建一个窗口,要求:
- 无边框,无标题栏
- 窗口半透明
- 自定义最大化,最小化,关闭按钮
- 支持拖拽用户区移动
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * class Window(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setWindowTitle("案例") # 设置标题 self.move_flag = False # 默认没有移动 self.resize(500, 500) # 设置窗口大小 self.move(300, 300) # 移动窗口 self.setWindowOpacity(0.9) # 设置窗口透明 self.setup_ui() # 调用创建控件的方法 self.origin = () # 初始坐标,相对于窗口的 self.mouse = () # 鼠标按下时,鼠标相对于窗口的坐标 def setup_ui(self): # 添加控件的操作 def close_w(): self.deleteLater() # 删除主窗口 btn_close = QPushButton(self) btn_close.clicked.connect(close_w) btn_close.setText("X") btn_close.move(self.width() - 25, 8) def max_or_min(btn): if self.isMaximized(): self.showNormal() btn.setText("+") else: self.showMaximized() btn.setText("-") count = 1 self.findChild(QLabel).resize(self.width(), 45) for i in self.findChildren(QPushButton): i.move(self.width() - count * 25, 8) # 动态化设置按键的位置 count += 1 btn_maxOrMin = QPushButton(self) btn_maxOrMin.move(self.width() - 50, 8) btn_maxOrMin.clicked.connect(lambda: max_or_min(btn_maxOrMin)) btn_maxOrMin.setText("+") qApp.setStyleSheet("""QPushButton{ font-size: 20px; color: black; font-weight: 800; border: 2px solid black; margin: 5px; }""") # 设置样式 # 设置窗口头部框架 label = QLabel(self) label.resize(self.width(), 45) label.setStyleSheet("background-color: skyblue;") label.lower() # 设置窗口移动 def mousePressEvent(self, evt): if evt.button() == Qt.LeftButton: self.move_flag = True self.mouse = (evt.globalX(), evt.globalY()) self.origin = (self.x(), self.y()) def mouseMoveEvent(self, evt): self.move(evt.globalX() - self.mouse[0] + self.origin[0], evt.globalY() - self.mouse[1] + self.origin[1]) if self.move_flag else None def mouseReleaseEvent(self, *args, **kwargs): self.move_flag = False if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口,同时无边框,无标题栏 w = Window(flags=Qt.FramelessWindowHint) # 显示窗口 w.show() sys.exit(app.exec_())
2.12 交互状态
2.12.1 是否可见
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ setEnabled(bool) # 设置控件是否可用 isEnabled() # 获取控件是否可用 """ app = QApplication(sys.argv) w = QWidget() btn = QPushButton(w) btn.setText("点击") print(btn.isEnabled()) # 判断按钮是否可用 btn.pressed.connect(lambda: btn.setEnabled(False)) # 点击后按钮禁用 w.show() sys.exit(app.exec_())
2.12.2 显示和隐藏
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ # 显示和隐藏 setVisible(bool) # 设置控件是否可见,传递的参数值为 True 也不一定可见,如果父控件没有展示,那么子控件为 True 也不可见 setHidden(bool) # 设置隐藏 show() # 设置显示 hide() # 设置隐藏 isHidden() # 获取相对于父控件是否隐藏 isVisible() # 获取是否可见 isVisibleTo(widget) # 获取相对于widget控件是否可见,即该控件是否跟着widget控件一起显示 """ app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) btn = QPushButton(w) print(btn.isVisible()) # 判断控件是否可见 btn.clicked.connect(lambda: btn.hide()) # 隐藏按钮 print(w.isHidden()) # 判断窗口是否隐藏 w.setVisible(True) # 使得窗口可见,先绘制父窗口 # w.setHidden(False) # 效果一样 sys.exit(app.exec_())
2.12.3 是否可编辑
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ setWindowModified(bool) # 设置是否被编辑 isWindowModified() # 窗口是否被编辑 """ app = QApplication(sys.argv) w = QWidget() w.setWindowTitle("[*]交互状态") w.setWindowModified(True) # 可编辑状态会显示 [] 里面的*号,即有 * 号就处于被编辑状态 print(w.isWindowModified()) # 判断窗口是否处于可编辑状态 w.setVisible(True) # 和show作用类似 sys.exit(app.exec_())
2.12.4 是否为活跃窗口
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w1 = QWidget() w2 = QWidget() w2.show() w1.show() print(w2.isActiveWindow()) # 展示是否处于活跃窗口 print(w1.isActiveWindow()) sys.exit(app.exec_())
2.12.5 控件关闭
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ setAttribute(Qt.WA_DeleteOnClose, True) # 如果加了这行代码,窗口/控件就会在关闭的同时删除,效果和deleteLater类似 close() # 效果和setVisible类似 """ app = QApplication(sys.argv) w1 = QWidget() w2 = QWidget() w2.destroyed.connect(lambda: print("w2销毁")) w1.destroyed.connect(lambda: print("w1销毁")) w2.show() w1.show() w1.setAttribute(Qt.WA_DeleteOnClose, True) # 如果加了这行代码,窗口/控件就会在关闭的同时删除,效果和deleteLater类似 w1.close() # 效果和setVisible类似 w2.setVisible(False) # 使得窗口不可见,但是窗口并没有删除 w2.deleteLater() # 销毁窗口/控件 sys.exit(app.exec_())
2.12.6 案例
创建一个窗口,包含一个文本框和一个按钮和一个标签:
- 默认状态下,标签隐藏,文本框和按钮显示,按钮为不可使用状态
- 当文本框有内容时,让按钮可用,否则不可用
- 当文本框内容为kun时,点击按钮显示标签,并且展示文本为登录成功,否则为失败
涉及知识点:
- 文本框的创建
- QLineEdit类
- 文本框内容监测
- testChanged 信号
- 文本框内容获取
- text() 方法
- 按钮状态设置
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import hashlib class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("案例[*]") # 设置标题 self.resize(500, 500) # 设置窗口大小 self.move(100, 100) # 移动窗口 self.setup_ui() # 调用创建控件的方法 def setup_ui(self): # 添加控件的操作 5 + 40 + 5 + 40 + 5 qApp.setStyleSheet("*{font-size: 15px; line-height: 15px;}") # 设置样式 # 创建文本框 text = QLineEdit(self) text.resize(300, 40) text.move(100, 5) def change_(): self.setWindowModified(True) btn.setEnabled(len(text.text()) > 0) # 当有文本框内容时,按钮可用 text.textChanged.connect(change_) # 绑定事件 # 创建按钮 btn = QPushButton(self) btn.resize(80, 40) btn.setText("登录") btn.move(210, 50) btn.setEnabled(False) # 按钮不可用 def click_(): label.setVisible(True) # 显示标签 # 使用 hash 加密 salt = hashlib.md5("liu".encode("utf-8")) salt.update(text.text().encode("utf-8")) content = salt.hexdigest() if content == 'a8b2a2561ec21479990c48706a743c9a': # 条件判断 label.setText("登录成功") else: label.setText("登录失败") text.setText("") self.setWindowModified(False) btn.clicked.connect(click_) # 绑定事件 # 创建标签 label = QLabel(self) label.resize(100, 40) label.move(220, 95) label.setVisible(False) # 标签隐藏 if __name__ == '__main__': # 可以通过导包来运行窗口 import sys app = QApplication(sys.argv) # 创建窗口 w = Window() # 显示窗口 w.show() sys.exit(app.exec_())
2.13 信息提示
2.13.1 状态提示
鼠标悬停在空间上一会儿后,展示内容在状态栏上面
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QMainWindow() # 使用组合窗口 w.resize(500, 500) w.statusBar() # 创建状态栏,可以显示状态提示 l = QLabel(w) l.setStatusTip("这是信息提示") # 设置状态提示 l.setText("你好") print(l.statusTip()) # 获取状态提示 w.show() sys.exit(app.exec_())
2.13.2 工具提示
鼠标悬停在控件上一会儿后,展示在旁边
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) l = QLabel(w) l.setToolTip("这是一个工具提示") l.setText("坤坤") l.setToolTipDuration(1000) # 工具提示展示时间为 1 秒 print(l.toolTip()) # 获取工具提示 w.show() sys.exit(app.exec_())
2.13.3 意思提示
切换到查看这是啥模式,点击该控件时显示
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys app = QApplication(sys.argv) w = QWidget(flags=Qt.WindowContextHelpButtonHint) # 这是啥模式 w.resize(500, 500) l = QLabel(w) l.setWhatsThis("这是啥,这是一个意思提示") # 设置一个意思提示 l.setText("坤坤") print(l.whatsThis()) # 获取意思提示 w.show() sys.exit(app.exec_())
2.14 焦点控制
2.14.1 单个控件
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ setFocus() # 指定控件获取焦点 setFocusPolicy(mode) # 设置焦点获取策略 - 参数 Qt.TabFocus 通过 Tab 获取焦点 Qt.ClickFocus 通过点击获取焦点 Qt.StrongFocus 通过以上两种方式获取焦点 Qt.NoFocus 不能通过以上两种方式获取焦点 clearFocus() # 取消焦点 """ app = QApplication(sys.argv) # 创建三个文本框 w = QWidget() w.resize(500, 500) t1 = QLineEdit(w) t2 = QLineEdit(w) t2.move(50, 50) t2.setFocus() # 设置焦点 t2.setFocusPolicy(Qt.TabFocus) # 获取焦点的方式 t2.clearFocus() # 取消焦点 t3 = QLineEdit(w) t3.move(100, 100) w.show() sys.exit(app.exec_())
2.14.2 父控件
#!/usr/bin/env python # -*- coding: UTF-8 -*- # @author: kun from PyQt5.Qt import * import sys """ focusWidget() # 获取子控件中当前焦距的控件 focusNextChild() # 聚焦下一个子控件 focusPreviousChild() # 聚焦上一个子控件 focusNextPrevChild() # true:下一个 false:上一个 setTabOrder(pre_widget, next_widget) # 静态方法,用于设置子控件获取焦点的先后顺序 """ app = QApplication(sys.argv) w = QWidget() w.resize(500, 500) t1 = QLineEdit(w) t1.setFocus() # 给 t1 设置焦点 t2 = QLineEdit(w) t2.move(50, 50) t3 = QLineEdit(w) t3.move(100, 100) w.show() # QWidget.setTabOrder(t3, t2) # 按 tab 获取焦点的顺序 t3 > t2 > t1 w.focusNextChild() # 聚焦下一个子控件 w.focusNextPrevChild(True) # 结果是t3有焦点 print(w.focusWidget()) # 获取子控件中当前焦距的控件 sys.exit(app.exec_())
2.15 信号
windowTitleChanged(QString) # 窗口标题改变信号 windowIconChanged(QIcon) # 窗口图标改变信号 customContentMenuRequested(Qpoint) # 自定义上下文菜单请求信号
基类控件学习完成,下面我们开始学习具体的子类控件
本文来自博客园,作者:Kenny_LZK,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/16071371.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器