pyQt5 学习笔记(6)设置鼠标(光标)样式

一、光标简介

通常我们的鼠标在不同的状态下会显示不同的形状,来提示用户当前的状态,如忙碌,拖拽,禁止,改变窗体大小等:
在这里插入图片描述
当然,严格来说,鼠标是硬件,而我们屏幕上看到的随着鼠标的移动而移动的图像称为光标(Cursor),在pyQt5中,我们可以很方便的设置一个控件的光标样式,也就是当鼠标移动到这个控件上时,显示的图像。

二、光标的设置

1. 程序示例

光标的设置只需要使用setCurror()即可,以下示例了如何设置光标的样式:

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)

# 创建一个父控件
window = QWidget()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor")

# 创建2个子控件
w1 = QWidget(window)
w1.move(148,150)
w1.resize(100,100)
w1.setStyleSheet('background-color:red;')

w2 = QWidget(window)
w2.move(250,150)
w2.resize(100,100)
w2.setStyleSheet('background-color:blue;')

# 定义鼠标的样式
w1.setCursor(Qt.WaitCursor)             #设置光标为:等待
w2.setCursor(Qt.SizeAllCursor)          #设置光标为:移动

window.show()!

if __name__ == '__main__':
    sys.exit(app.exec_())

其程序效果如下:
在这里插入图片描述
可以看到,在红蓝两个不同控件上时候,光标的样式是不一样的。

2. 参数查询

上文演示了2个样式的光标,那么如何设置其他的样式呢?这就需要查看Qt的文档,在Qt相关的文档里面,已经给用户列好表格,给出光标的样式,以及一般的用途:
在这里插入图片描述
如果我们需要显示SizeFDiagCuror的光标,就在将Qt.SizeFDiagCursor这个参数填入setCursor()中即可,即:setCursor(Qt.SizeFDiagCursor)

三、自定义光标

1. 素材准备

在游戏界面,通常不会使用我们系统的鼠标,Qt也可以自定义光标样式,首先需要准备一个或者是系列图标,这里预先准备了一个简约的光标:
在这里插入图片描述

2. 程序设计

2.1 一个简单的程序

简单的定义一个光标需要以下三步:

  1. 创建一个图形对象
  2. 将图形对象传入鼠标对象
  3. 使用setCursor()方法设置对象

以下是程序示例:

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)

# 创建一个控件
window = QWidget()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor")

#1. 创建光标的图像,参数为光标的相对位置(本文将光标存在工程目录的Cursor_png文件夹下)
pixmap = QPixmap('Cursor_png/01.png')
#2. 将光标对象传入鼠标对象中
cursor = QCursor(pixmap)
#3. 设置控件的光标
window.setCursor(cursor)

window.show()

if __name__ == '__main__':
    sys.exit(app.exec_())

其运行效果如下所示:
真TM大

2.2 调整光标

上图我们导入了一个光标,但是它显然太大了,我们需要通过程序将其设置小一些,另外,非常大的光标让我们注意到一个问题:如果此时有一个按钮,那么这个光标的哪个位置放在按钮上面,才可以单击按钮?是光标的头部还是光标的尾部,还是光标的任意一个地方?这同样可以通过程序来设置,以下是改进后的程序:

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)

# 创建一个父空间
window = QWidget()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor")

#1. 创建光标的图像,参数为光标的相对位置
pixmap = QPixmap('Cursor_png/01.png')
#2. 创建一个新的图像,为原素材缩小到15*20大小
new_pixmap = pixmap.scaled(15,20)
#3. 将新光标对象传入鼠标对象中,并将鼠标热点设为左上角
cursor = QCursor(new_pixmap,0,0)
#4. 设置控件的光标
window.setCursor(cursor)

window.show()

if __name__ == '__main__':
    sys.exit(app.exec_())

程序运行如下所示:
在这里插入图片描述
程序使用 new_pixmap = pixmap.scaled(15,20)来生成一个新的对象,这是因为scaled将重新修改大小后的图像作为一个新对象返回,而不是修改原对象本身,这和pygame操作是一样的。所以我们创建一个new_pixmap对象存储这个返回的对象。其中,第一个参数为宽度,第二个参数为高度
程序还定义了鼠标的热点,即有效的像素为(0,0),通过 QCursor(new_pixmap,0,0) 的第3,4个参数来设置,如果你不太了解这个概念,可以自行修改这2参数,然后去尝试点击最小化或者其他控件,来感受一下这2个参数的作用。

2.3 其他API

这里在继续介绍光标的其他常用的接口函数:

  • 恢复鼠标样式:unsetCursor()
  • 获取鼠标坐标:cursor.pos()
  • 设置鼠标位置:setPos(200,200)
  • 鼠标跟踪(获取鼠标的x.y值):mouseMoveEvent()

以下程序示例了这三个函数的使用:

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)

# 创建一个父空间
window = QWidget()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor")

pixmap = QPixmap('Cursor_png/01.png')
new_pixmap = pixmap.scaled(15,20)
cursor = QCursor(new_pixmap,0,0)

#1. 设置控件的光标
window.setCursor(cursor)
#2. 恢复鼠标默认值
window.unsetCursor()
#3. 获取鼠标对象
cursor = window.cursor()
#4. 设置鼠标位置
cursor.setPos(200,200)
#5. 打印鼠标的位置
print(cursor.pos())

其运行结果如下:
在这里插入图片描述
程序第17虽然设置了光标的样式,但是在18行又将其取消了,所以光标的样式并没有改变,接着程序获取了当前光标对象,然后设置它的坐标,此时运行后你会发现鼠标跑到屏幕(200,200)的位置,最后程序将鼠标的值打印了出来。这里的坐标都是相对于显示器屏幕的。

上文代码演示了鼠标光标位置,获取光标坐标和恢复光标演示API函数的使用,接下来示例鼠标跟踪程序的实现。鼠标跟踪指的是获取当前鼠标的位置,可以是相对屏幕的位置,也可以是相对当前控件的位置,它是通过mouseMoveEvent()来获取的,当开启鼠标跟踪以后(setMouseTracking(True))程序会一直记录鼠标的位置,然后作为事件派送给mouseMoveEvent()函数。
以下是示例程序:

from PyQt5.Qt import *
import sys

#1. 自定义一个QWidget对象
class MyWindow(QWidget):
    #2. 重定义鼠标事件
    def mouseMoveEvent(self, QMouseEvent):
        print("当前鼠标坐标:", QMouseEvent.pos())

app = QApplication(sys.argv)

#创建一个父空间
window = MyWindow()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor")

#3. 启动鼠标跟踪
window.setMouseTracking(True)

window.show()

if __name__ == '__main__':
    sys.exit(app.exec_())

其运行效果如下所示:
在这里插入图片描述
可以看到,当鼠标在窗体中移动的时候,pyCharm的控制台源源不断的打印出鼠标的坐标。注意到,代码第19行我们还使用了window.setMouseTracking(True)来使能光标跟踪,如果没有这句代码,那么只有鼠标被按下状态时,才会被跟踪。这里鼠标的坐标获取的是相对于窗体的坐标,如果我们需要获取相对于屏幕的坐标,可以将第8行print函数中的QMouseEvent.pos()改为QMouseEvent.globalPos(),当然了,依然只有当鼠标的光标在窗体上运动时,才会被跟踪到。

四、练习

综合以上的内容,我们来创建一个自定义光标样式的控件(QWidget),并建立一个跟随鼠标的标签(QLabel),并且这个标签实时显示鼠标的坐标。

1. 素材准备

自定义鼠标样式,就需要准备一个素材,这里重新选择一个光标素材:
在这里插入图片描述

2. 程序实现

由于此处程序分步实现,每一步只贴出新增或修改部分,其他用分号表示省略,程序运行效果也选择性略过,完整程序最后再统一贴出。

2.1 创建一个基本控件和标签

首先创建一个最基本的控件:

from PyQt5.Qt import *
import sys

#创建一个APP
app = QApplication(sys.argv)

#创建一个基本窗体
window = QWidget()
window.resize(500,500)
window.move(300,300)
window.setWindowTitle("Cursor Trace")
#创建一个label
label = QLabel(window)
label.setText('(x,y)')
label.move(100,100)
label.setStyleSheet('background:green;font-size:25px;')


window.show()

if __name__ == '__main__':
    sys.exit(app.exec_())

2.2 标签跟随光标

  1. 光标的位置的获取
from PyQt5.Qt import *
import sys

# 创建一个APP
app = QApplication(sys.argv)

# 创建一个新的类
class MyWindow(QWidget):
    # 定义鼠标事件
    def mouseMoveEvent(self, ev):
        print("当前鼠标坐标:", ev.globalPos())

# 创建一个基本窗体,需要修改为新的类
window = MyWindow()
··· ···
# 创建一个label
label = QLabel(window)
··· ···
# 使能光标跟随
window.setMouseTracking(True)

window.show()

if __name__ == '__main__':
    sys.exit(app.exec_())
  1. 设置标签的位置及其显示的值
    这里我们还把上面的代码封装成一个类,这样可以统一创建一个对象,方便管理,完整代码如下所示:
from PyQt5.Qt import *
import sys

#创建一个APP
app = QApplication(sys.argv)

class MyWindow(QWidget):
    # 创建一个基本窗体
    def __init__(self):
        super().__init__()
        self.resize(500, 500)
        self.move(300, 300)
        self.setWindowTitle("Cursor Trace")

        self.label = QLabel(self)
        self.label.setText('')

        self.label.move(100, 100)
        self.label.setStyleSheet('background:green;font-size:25px;')

        self.setMouseTracking(True)
        self.show()

    def mouseMoveEvent(self, ev):
        x = ev.localPos().x()
        y = ev.localPos().y()
        self.label.move(x,y)
        # 设置标签的显示
        self.label.setText('('+str(y)+' '+str(x)+')')
        # 自适应大小:因为x的坐标可能是0,有可能是100,y同理,所以label长度需要自适应
        self.label.adjustSize()
        print("当前鼠标坐标:", x, y)

window = MyWindow()

if __name__ == '__main__':
    sys.exit(app.exec_())

2.3 自定义光标

自定义光标需要创建一个类,并导入图片,具体程序如下:

...
        self.pixmap = QPixmap('Cursor_png/arrows.png')
        self.new_pixmap = self.pixmap.scaled(15, 20)
        self.cursor = QCursor(self.new_pixmap, 0, 0)
...

2.3 完整代码

当自定义鼠标光标以后,程序的功能就都完成了,以下是完整的代码:

from PyQt5.Qt import *
import sys

#创建一个APP
app = QApplication(sys.argv)

class MyWindow(QWidget):
    # 创建一个基本窗体
    def __init__(self):
        super().__init__()

        self.resize(500, 500)
        self.move(300, 300)
        self.setWindowTitle("Cursor Trace")

        self.label = QLabel(self)
        self.label.setText('')

        self.label.move(100, 100)
        self.label.setStyleSheet('background:green;font-size:25px;')

        self.setMouseTracking(True)

        self.pixmap = QPixmap('Cursor_png/arrows.png')
        self.new_pixmap = self.pixmap.scaled(15, 20)
        self.cursor = QCursor(self.new_pixmap, 0, 0)

        self.setCursor(self.cursor)

        self.show()

    def mouseMoveEvent(self, ev):
        x = ev.localPos().x()
        y = ev.localPos().y()
        # 将label显示在右下角
        self.label.move((x+15),(y+20))
        self.label.setText('('+str(y)+' '+str(x)+')')
        self.label.adjustSize()
        print("当前鼠标坐标:", x, y)

window = MyWindow()

if __name__ == '__main__':
    sys.exit(app.exec_())

程序运行下过如下:
在这里插入图片描述

3. 程序的不足与优化

上述的程序实现了基本的功能,但是它有一些明显的不足:

  • 光标在靠近边框右侧时候,由于显示坐标的label是子控件,所以导致部分不被显示,如下所示:
    在这里插入图片描述
  • 光标由于在label上不被跟踪,所以导致有时候看起来label没有在跟踪鼠标(这种情不易出现)在这里插入图片描述
  • 像素点坐标肯定是整数,这里不需要显示一位小数

以上不足可以通过简单的逻辑处理规避,这里不再赘述。

  • 21
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值