【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 中最重要的一部分内容:事件

整理不易,希望大家点个赞,收藏一个再走吧,要是能点个关注就更感激不尽了。

在这里插入图片描述

想要笔记原文的,可留意或私信。

猜你喜欢

转载自blog.csdn.net/zhouz92/article/details/106734918