赞
踩
基于widget的应用程序都是由事件event驱动的,像鼠标单击、按下某个按键、重回组件、最小化窗口等都会产生相应的事件。
- app = QApplication(sys.argv)
- form = QWidget()
- form.show()
- sys.exit(app.exec_())
最后执行的app.exec_()开启了应用程序的事件处理循环。
应用程序会对事件队列中排队的事件进行处理,还可以对相同事件进行合并处理。
PyQt5中,事件是一种对象,事件的基类是抽象类QEvent。
QEvent有众多子类表示具体的事件,例如QKeyEvent表示按键事件,QMouseEvent表示鼠标事件,QPaintEvent表示窗体绘制事件。
当一个事件发生时,PyQt5会根据事件的具体类型用QEvent相应的子类创建一个事件对象,然后传递给产生事件的对象的event()函数进行处理。
event(self,e)
event函数的参数e就是PyQt5调用event函数时传入的事件对象。
QEvent类定义了三个接口函数:
accept() 表示事件接收者接受此事件。被接受的事件不会再继续向上传播给上层容器组件。
ignore() 表示事件接收者忽略此事件。被忽略的事件会继续向上传播给上层容器组件。
type() 返回事件的类型。事件类型是枚举,每一个枚举值都对应一个PyQt5的具体事件类型。例如QMouseEvent的type枚举值为5。不同事件类型对应的枚举值可以参考官方文档。
事件会优先发送给触发事件对象的event函数,但是event函数默认是不做额外的具体处理,而是将事件转派给触发事件对象的各种事件的默认处理函数。例如:event函数会将type为QMouseEvent事件会转派给触发事件对象的mouseMoveEvent()函数,会将type为QMouseButtonDblClick事件会转派给触发事件对象的mouseDoubleClickEvent()函数。
每一个QWidget都定义了很多这样的默认事件处理函数,都会接受一个具体的event事件对象。每一个具体的event对象出了实现基础QEvent对象的接口之外,还会提供很多其它的与事件相关的函数。例如QMouseEvent对象还提供了返回鼠标位置的pos()/localPos()等函数。
用户在继承QWidget或者其子类的自定义类型中可以重新实现这些默认的事件处理函数,从而实现一些需要的功能。例如,某些组件没有clicked信号,那么就不能通过信号与槽的方式实现对鼠标单击的处理,但是可以重新实现mousePressEvent()或mouseReleaseEvent()函数对鼠标事件进行处理。
事件与信号是有区别的,但是也有关联。Qt为某个界面组件定义的信号通常是对某个事件的封装。例如QPushButton有clicked信号,就可以看做是对QPushButton的QMouseReleaseEvent事件的封装。通过编写与信号关联的槽函数可以实现当信号发射时做的事情。一个信号可以关联多个槽函数,一个槽函数也可以关联多个信号。
通过创建PyQt5.QtCore.pyqtSignal对象可以实现自定义信号。调用自定义信号的emit函数就可以将信号发射出去,触发与信号关联的槽函数。
- class QmyLabel(QLabel):
- doubleClicked = pyqtSignal()
- def mouseDoubleClickEvent(self,event):
- self.doubleClicked.emit()
-
- class QmyWidget(Qwidget):
- def __init__(self,parent=None):
- super().__init__(parent)
- self.resize(300,300)
- self.setWindowTitle('自定义信号')
-
- myLab = QmyLabel(self)
- myLab.setText('I am Label')
- font = myLab.font()
- font.setPointSize(14)
- font.setBold(True)
- myLab.setFont(font)
- size = myLab.sizeHint()
- myLab.setGeometry(70,60,size.width(),size.height())
- myLab.doubleClicked.connect(self.do_doubleClicked)
-
-
- def do_doubleClicked(self):
- print('Label is DoubleClicked!')
-
- def mouseDoubleClickEvent(self,event):
- print('Window is DoubleClicked')
-
- if __name__=='__main__':
- app = QApplication(sys.argv)
- form = QmyWidget()
- form.show()
- sys.exit(app.exec_())

QmyLabel自定义了一个doubleClicked信号。当QmyLabel上发生了鼠标双击事件时,会将鼠标双击事件委派给QmyLabel的mouseDobleClickEvent函数处理,处理的方式就是发射自定义信号doubleClicked。
在QmyWidget中,doubleClicked函数的槽函数是QmyWidget的do_doubleClicked函数。该函数一旦检测到doubleClicked信号,槽函数就会执行,在控制台输出Label is DoubleClicked。
通过使用PyQt5的事件过滤器(eventfilter),可以将一个对象上发生的事件委托给另一个对象来检测并处理。
实现事件过滤功能需要完成以下两项操作:
1. 被监测对象使用installEvenFilter()函数将自己注册给监测对象。
2.监测对象实现eventFilter()函数,对监测对象的事件进行处理。
- import sys
- from PyQt5.QtWidgets import QApplication, QLabel,QWidget,QLabel
- from PyQt5.QtCore import Qt,QEvent
-
-
- class QmyWidget(QWidget):
- def __init__(self, parent=None) -> None:
- super().__init__(parent)
- self.resize(400,400)
- self.setWindowTitle('事件委托')
- self.laba = QLabel(self)
- self.laba.setText('I am Label A')
- font = self.laba.font()
- font.setPointSize(10)
- font.setBold(True)
- self.laba.setFont(font)
- self.laba.setGeometry(20,20,300,60)
- self.laba.installEventFilter(self)
- self.labb = QLabel(self)
- self.labb.setText('I am Label B')
- font = self.labb.font()
- font.setPointSize(10)
- font.setBold(True)
- self.labb.setFont(font)
- self.labb.setGeometry(20,100,300,60)
- self.labb.installEventFilter(self)
- def eventFilter(self, w, e) -> bool:
- if w == self.laba:
- if e.type()==QEvent.Enter:
-
- self.laba.setText('鼠标来啦')
- self.laba.setStyleSheet('background-color:rgb(170,255,255);')
- if e.type()==QEvent.Leave:
- self.laba.setText('I am Label A')
- self.laba.setStyleSheet('')
- if w == self.labb:
- if e.type()==QEvent.Enter:
- self.labb.setText('点我!')
- self.labb.setStyleSheet('background-color:rgb(85,255,127);')
- if e.type()==QEvent.MouseButtonPress:
- self.labb.setText('还真点啊!')
- self.labb.setStyleSheet('background-color:rgb(85,255,127);')
- if e.type()==QEvent.MouseButtonRelease:
- self.labb.setText('点我!')
- self.labb.setStyleSheet('background-color:rgb(85,255,127);')
- if e.type()==QEvent.Leave:
- self.labb.setText('I am Label B')
- self.labb.setStyleSheet('')
- return super().eventFilter(w, e)
-
- app = QApplication(sys.argv)
- form = QmyWidget()
- form.show()
- sys.exit(app.exec_())

QmyWidget充当窗口,里面有两个QLabel,laba和labb,它们将事件处理全部委托给了QmyWidget。这样,一旦有发生在laba和labb上的事件,QmyWidget的eventFilter函数就会被触发。当然QmyWidget也并不会处理laba和labb的所有事件,所以会通过条件语句判定事件源和事件类型。最后,也是最重要的,因为并不是对laba和labb的事件都做处理,所以一定要使用QWidget的eventFilter函数做善后处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。