PyQT5 学习笔记:第三节 QWidget类 鼠标QCursor 设置、父子关系、层级关系API及用法实例
前言:
上一节的内容介绍了QWidget类中窗口创建、大小设置及内容边距等API及用法的知识点。
本节主要对QWidget类中的鼠标设置、父子关系及层级关系进行讲解。
1 鼠标设置API及用法实例
1.1 API一览
项目 | 说明 |
---|---|
setCursor() | 设置鼠标形状 |
unsetCursor() | 重置形状 |
cursor() | 获取鼠标 |
setMouseTracking(bool) | 设置鼠标是否跟踪 |
hasMouseTracking() | 判定是否设置了鼠标跟踪 |
QCursor | 鼠标对象 |
pos() | 获取鼠标位置 |
setPos(x, y) | 设置鼠标位置坐标 |
1.2 PyQT5自带的鼠标形状
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.SplitVCursor
Qt.SplitHCursor
Qt.OpenHandCursor
Qt.ClosedHandCursor
Qt.BlankCursor
1.3 API测试
设置鼠标形状:
可以设置整个窗口的鼠标形状,也可以设置窗口中某一控件的鼠标形状。
import sys
from PyQt5.Qt import
app = QApplication(sys.argv)
window = QWidget()
window.resize(300,200)
# 设置鼠标形状,在窗口中的形状
window.setCursor(Qt.OpenHandCursor)
button = QPushButton(window)
button.move(0,50)
button.setText('按钮控件')
# 设置鼠标在按钮控件上的形状
button.setCursor(Qt.PointingHandCursor)
window.show()
sys.exit(app.exec_())
效果图:
自定义鼠标形状:
创建通过创建QCursor对象,可以自定义鼠标形状。
QCursor(QPixmap, hotX: int = -1, hotY: int = -1)
QPixmap:图片对象;
hotX 与 hotY :自定义鼠标图像的点击基点,默认值都为:-1,指图片的中心位置。
这里我们引用两张图片:
z1.png
z2.png
代码:
window2 = QWidget()
window2.resize(300,200)
window2.setCursor(QCursor(QPixmap('z1.png')))
c2_label = QLabel(window2)
c2_label.setText('标签控件')
c2_label.resize(100,100)
c2_label.setStyleSheet('background-color:red;')
window2.show()
将上面窗口的label标签也设置一个自定义的鼠标对象(木锤砸下的形状),仔细观察鼠标移动到什么位置,其形状才发生变化。
my_cursor = QCursor(QPixmap('z2.png'))
c2_label.setCursor(my_cursor)
仔细看图:
解析:
可以看到抬起的木锤形状在往标签控件移动过程中,直到移动到木锤的中间位置,才变成砸下的木锤形状。
即:窗口控件的鼠标的按下基点在锤子的中间位置。
改变自定义鼠标的点击基点:
设置 hotX 与 hotY :
window2.setCursor(QCursor(QPixmap('z1.png'),hotX=0,hotY=0))
hotX=0,hotY=0 :图片对象的左上角。
看图: 鼠标移动到木锤图片的左上角时,鼠标形状就发生了变化。
window2.setCursor(QCursor(QPixmap('z1.png'),hotX=100,hotY=100))
hotX=100,hotY=100 :图片对象的右下角(z1.png图像大小约为100px , 100 px)。
鼠标跟踪:
所谓的鼠标跟踪,其实就是设置检测鼠标移动事件触发的条件(mouseMoveEvent)。
不跟踪: 鼠标移动时,必须处于按下状态,才会触发mouseMoveEvent事件;
跟踪: 鼠标移动时,不处于按下状态,也会触发mouseMoveEvent事件。
# 鼠标跟踪
class MyWidget(QWidget):
def mouseMoveEvent(self,event):
# 获取鼠标位置
print(self.cursor().pos())
window3 = MyWidget()
window3.resize(400,400)
# 设置鼠标跟踪,True,False
window3.setMouseTracking(True)
# 所谓的鼠标跟踪,其实就是设置检测鼠标移动事件的条件 mouseMoveEvent
# 不跟踪:鼠标移动时,必须处于按下状态,才会触发mouseMoveEvent事件
# 跟踪:鼠标移动时,不处于按下状态,也会触发mouseMoveEvent事件
# 查看鼠标是否跟踪
print(window3.hasMouseTracking())
window3.show()
效果图:
解析:
这里自己写了一个MyWidget类,在类中重写了mouseMoveEvent方法;
将窗口的鼠标跟踪设置为真;
鼠标在窗口移动时因鼠标跟踪设置为真,所以会调用mouseMoveEvent方法,打印鼠标坐标。
注意:这里打印的cursor().pos()坐标是相对于屏幕的坐标,而不是相对于window3窗口的坐标。
1.4 实例:让窗口子控件跟随鼠标移动
要求:
1、创建一个窗口, 内部有一个label控件;
2、鼠标移入窗口时, 让label位置跟随鼠标位置。
代码:
class MyWidget2(QWidget):
def __init__(self):
super(MyWidget2, self).__init__()
self.label = QLabel(self)
self.label.setStyleSheet('background-color:red')
self.label.resize(100,100)
# 重写鼠标移动事件
def mouseMoveEvent(self, event):
# 将鼠标坐标绑定label控件位置坐标
self.label.move(self.cursor().pos().x()-self.x(),
self.cursor().pos().y()-self.y())
print(self.cursor().pos())
window4 = MyWidget2()
window4.resize(600,500)
# 打开鼠标跟踪
window4.setMouseTracking(True)
window4.show()
效果图:
从上面的效果图可以看到:当鼠标进入窗口后,label标签的确会跟随鼠标的移动而移动。但是标签的定点坐标却不是鼠标的坐标。
这是因为:获得的坐标点并不准确。
self.label.move(self.cursor().pos().x()-self.x(),self.cursor().pos().y()-self.y())
self.x() 与 self.y() 获取到的是窗口顶点(包含窗口框架)坐标,应用 self.geometry() 里的 x 与 y 坐标。(对于这一内容不太熟悉的,可以查看上一节的 学习笔记 。)
将move方法里的坐标改为:
self.label.move(self.cursor().pos().x() - self.geometry().x(),
self.cursor().pos().y() - self.geometry().y())
效果图:
2 父子关系API及用法实例
2.1 API一览
我们在介绍QObject时也提及过父子关系,在QWidget类中也有父子关系相关的API。
项目 | 说明 |
---|---|
childAt(x, y) | 获取在指定坐标的控件 |
parentWidget() | 获取指定控件的父控件 |
childrenRect() | 所有子控件组成的边界矩形 |
2.2 API 测试
window5 = QWidget()
window5.resize(500,400)
w5_label = QLabel(window5)
w5_label.resize(100,50)
w5_label.setStyleSheet('background-color:red')
# 通过位置获取子控件
print(window5.childAt(10, 10))
# ------运行结果------
# <PyQt5.QtWidgets.QLabel object at 0x000002262CEB4CA8>
# ------运行结果------
# 获取指定控件的父控件
print(w5_label.parentWidget())
# ------运行结果------
# <PyQt5.QtWidgets.QWidget object at 0x0000025EC7DF5C18>
# ------运行结果------
# 所有子控件组成的边界矩形
print(window5.childrenRect())
# ------运行结果------
# PyQt5.QtCore.QRect(0, 0, 100, 50)
# ------运行结果------
window5.show()
大家可以查看第一节:QObject类 里的父子关系的相关API及用法。
2.3 实例:点击子控件标签,使其背景颜色改变
要求:
1、创建 窗口, 包含若干Label控件;
2、点击哪个标签, 就让哪个标签背景变红;
3、使用父控件处理, 不要自定义QLabel子类。
代码:
class MyWidget3(QWidget):
def mousePressEvent(self, event):
# 注意此处获取坐标位置的方法
local_x = event.x()
local_y = event.y()
sub_widget = self.childAt(local_x, local_y)
if sub_widget is not None:
sub_widget.setStyleSheet("background-color: red;")
window6 = MyWidget3()
window6.resize(300,400)
for i in range(1, 6):
label = QLabel(window6)
label.setText("标签" + str(i))
label.move(0, 50*i)
window6.show()
解析:
自定义了一个MyWidget3,重写了mousePressEvent事件,该事件是鼠标点击事件。
在该事件里增加了让窗口子控件背景颜色改为红色的语句。
效果图:
3 层级控制API及用法实例
3.1 API
项目 | 说明 |
---|---|
lower() | 将控件降低到最底层 |
raise_() | 将控件提升到最上层 |
a.stackUnder(b) | 让a放在b下面 |
注意:以上操作专指同级控件
3.2 API 测试
window7 = QWidget()
window7.resize(400,400)
c7_widget = QLabel(window7)
c7_widget.resize(150,150)
c7_widget.setStyleSheet('background:red')
c7_widget.move(50,50)
c8_widget = QLabel(window7)
c8_widget.resize(150,150)
c8_widget.setStyleSheet('background:blue')
c8_widget.move(100,100)
c9_widget = QLabel(window7)
c9_widget.resize(150,150)
c9_widget.setStyleSheet('background:green')
c9_widget.move(150,150)
window7.show()
这里我们创建了一个窗口,依次在窗口中创建 红、蓝、绿 三个Label 标签。
效果图为:
分别来做以下操作:
1、将红色子控件放在最上层:
c7_widget.raise_()
2、将绿色控件放在最底层:
c9_widget.lower()
3、将蓝色控件放在绿色控件上层:
c9_widget.stackUnder(c8_widget)
3.3 实例:
要求:
将测试API接口页面改为:当鼠标点击哪个子控件,哪个子控件就在最上层显示。
代码:
这里我们采用两种方法来实现上述的需求,及分别从父控件和子控件方面进行操作。
方法一: 在父控件方面进行操作。
自定义一个父控件(顶层窗口)类:
class MyWidget4(QWidget):
def mousePressEvent(self, event):
# 注意此处获取坐标位置的方法
local_x = event.x()
local_y = event.y()
sub_widget = self.childAt(local_x, local_y)
if sub_widget is not None:
sub_widget.raise_()
window7 = MyWidget4()
window7.resize(400,400)
c7_widget = QLabel(window7)
c7_widget.resize(150,150)
c7_widget.setStyleSheet('background:red')
c7_widget.move(50,50)
c8_widget = QLabel(window7)
c8_widget.resize(150,150)
c8_widget.setStyleSheet('background:blue')
c8_widget.move(100,100)
c9_widget = QLabel(window7)
c9_widget.resize(150,150)
c9_widget.setStyleSheet('background:green')
c9_widget.move(150,150)
window7.show()
方法二: 在子控件方面进行操作。
自定义一个Label类:
class MyLabel(QLabel):
def mousePressEvent(self, event):
self.raise_()
把方法一代码里的 QLabel 改为 MyLabel类。
效果图:
最后:
以上就是本次QWidget中有关鼠标设置、父子关系及层级关系相关API及用法介绍的全部内容了。QWidget类中API和用法实在是太多了,而且重要的内容也很多。下一节准备介绍QWidget乃至整个PyQT5 中最重要的一部分内容:事件 。
整理不易,希望大家点个赞,收藏一个再走吧,要是能点个关注就更感激不尽了。
想要笔记原文的,可留意或私信。