自定义控件 - 补充1

画圆弧

调用 QPainter 对象的 drawArc 方法可以画一个圆弧,

drawArc 方法通常由6个参数,

前四个参数是 圆弧紧贴的外矩形的 左上角xy坐标 和 宽、高


后两个参数比较难的一些:分别是 圆弧的 起点角度跨越角度


圆弧的 起点角度 是 从3点钟方向开始算起, 0 就代表 3点钟位置,

逆时针每加1度,数值 加16

顺时针每加1度,数值 减16

如果圆弧的起点是12点钟位置,可以是 90*16 , 也可以是 -270*16


最后一个参数 跨越角度 ,就是圆弧的从起点到终点的角度,

逆时针每加1度,数值 加16

顺时针每加1度,数值 减16


如下

from PySide2 import  QtGui, QtWidgets 

class MyWidget(QtWidgets.QWidget):

    def paintEvent(self, e): 
        painter = QtGui.QPainter(self)  

        painter.drawRect(10, 10, 300, 300)

        # 画圆弧,起点角度为 0度 ; 跨越90度
        painter.drawArc(10, 10, 300, 300, 0, 90 * 16)

        # 画笔颜色改为红色        
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor('red'))
        painter.setPen(pen)

        # 画圆弧,起点角度为 90度 ; 跨越90度
        painter.drawArc(10, 10, 300, 300, 90*16, 90 * 16)

        # 画笔颜色改为蓝色        
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor('blue'))
        painter.setPen(pen)
        # 画圆弧,起点角度为 -90度 ; 跨越90度
        painter.drawArc(10, 10, 300, 300, -90*16, 90 * 16)
        
        painter.end() # 结束绘制
       
app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow()
window.resize(500, 500)

my = MyWidget(window)
my.move(0,0)
my.resize(500,500)

window.show()
app.exec_()

QPaintEvent 事件对象

QWidget 的 paintEvent 方法,被Qt框架调用时,会传入一个 QPaintEvent 对象

通过这个对象,我们可以得到当前控件绘制相关信息。

最常用的就是 这个对象的 rect() 方法

该方法返回一个 QtCore.QRect 类型的对象

QRect对象对应的就是当前控件的区域信息。

比如

width() 方法,就可以得到绘制区的宽度

height() 方法,就可以得到绘制区的宽度


    def paintEvent(self, e):

        rect = e.rect()
        width = rect.width()   # 绘制区的宽度
        height = rect.height() # 绘制区的高度

事件响应

继承自 QWidget 的控件,都可以响应 QWidget 相关的事件

比如: 键盘按键、鼠标点击拖拽、鼠标滚轮事件 等等。

当这些事件发生在一个 QWidget控件上时,Qt就会查看这个控件有没有实现这些事件 对应的处理函数。 如果有,就会执行对应的函数。

这些函数就是,事件响应函数。具体可以参考官方文档

这里我们介绍一些常见的事件响应

鼠标点击

当我们鼠标按键(左键、右键等)点击 QWidget控件时,分别针对鼠标按钮按下和抬起, 会触发 两个鼠标事件,导致Qt调用两个该控件函数函数:

mousePressEventmouseReleaseEvent


通常我们只要实现其中一个,比如 mousePressEvent 函数,放入鼠标点击要做的事件处理代码即可。


比如

from PySide2 import  QtGui, QtWidgets 

class QOutlet(QtWidgets.QWidget):

    def __init__(self,parent, color) -> None:
        super().__init__(parent)
        
        self.color = color
        self.setMinimumSize(70, 70)
        self.setMaximumSize(70, 70)

    def paintEvent(self, e):
        painter = QtGui.QPainter(self)
        pen = QtGui.QPen()
        pen.setWidth(1)

        pen.setColor(QtGui.QColor(self.color)) 
        painter.setPen(pen)
        painter.drawRect(0, 0, 60, 60)
        
        pen = QtGui.QPen()
        pen.setWidth(3)
        pen.setColor(QtGui.QColor(self.color))
        painter.setPen(pen)

        painter.drawLine(12,10,12,25)
        painter.drawLine(30,10,30,25)
        painter.drawLine(48,10,48,25)

        painter.drawLine(10,35,20,50)
        painter.drawLine(50,35,40,50)

        painter.end()

    # 实现插座控件点击事件处理
    def mousePressEvent(self, e):        
        print("插座控件被点击了")
        print("事件对象",e)
        print(e.button())    # 点击的哪个鼠标按键
        print(e.pos())       # 点击处相对于控件的坐标
        print(e.windowPos()) # 点击处相对于窗口的坐标
       
app = QtWidgets.QApplication()

window = QtWidgets.QMainWindow()
window.resize(500, 500)

my = QOutlet(window,'green')
my.move(10,10)

window.show()
app.exec_()

可以发现,mousePressEvent 有一个参数e,是当前发生的: 鼠标事件对象

所有的事件处理函数,都会接收一个事件对象参数, 这个事件对象,包含了事件的一些信息。

可以通过事件对象的方法(比如 上例中的button()、pos()等 )获取这些信息。

鼠标进入、离开

当 鼠标进入、离开 QWidget控件的 范围时,会分别触发对 enterEventleaveEvent 方法的调用

比如,可以在上面的控件代码中,添加如下两个方法

    def enterEvent(self, e) :
        print("进入我的范围") 
        
    def leaveEvent(self, e) :
        print("离开我的范围") 

这两个方法,通常可以用来实现 鼠标悬浮在控件上出现显示效果的变化。

比如 Qt的按钮控件,鼠标放在上面,底色会出现改变。

大家可以想一想具体怎么实现该功能

键盘按键

当,会分别触发对 keyPressEventkeyReleaseEvent 方法的调用

并且传入响应的键盘事件对象。


通常我们只要实现其中一个,比如 mousePressEvent 函数,放入鼠标点击要做的事件处理代码即可。