当前位置:   article > 正文

PyQt5的事件机制_qt源码中mousedoubleclickevent触发机制

qt源码中mousedoubleclickevent触发机制

基于widget的应用程序都是由事件event驱动的,像鼠标单击、按下某个按键、重回组件、最小化窗口等都会产生相应的事件。

应用程序的事件循环

  1. app = QApplication(sys.argv)
  2. form = QWidget()
  3. form.show()
  4. 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函数就可以将信号发射出去,触发与信号关联的槽函数。

  1. class QmyLabel(QLabel):
  2. doubleClicked = pyqtSignal()
  3. def mouseDoubleClickEvent(self,event):
  4. self.doubleClicked.emit()
  5. class QmyWidget(Qwidget):
  6. def __init__(self,parent=None):
  7. super().__init__(parent)
  8. self.resize(300,300)
  9. self.setWindowTitle('自定义信号')
  10. myLab = QmyLabel(self)
  11. myLab.setText('I am Label')
  12. font = myLab.font()
  13. font.setPointSize(14)
  14. font.setBold(True)
  15. myLab.setFont(font)
  16. size = myLab.sizeHint()
  17. myLab.setGeometry(70,60,size.width(),size.height())
  18. myLab.doubleClicked.connect(self.do_doubleClicked)
  19. def do_doubleClicked(self):
  20. print('Label is DoubleClicked!')
  21. def mouseDoubleClickEvent(self,event):
  22. print('Window is DoubleClicked')
  23. if __name__=='__main__':
  24. app = QApplication(sys.argv)
  25. form = QmyWidget()
  26. form.show()
  27. 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()函数,对监测对象的事件进行处理。

  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QLabel,QWidget,QLabel
  3. from PyQt5.QtCore import Qt,QEvent
  4. class QmyWidget(QWidget):
  5. def __init__(self, parent=None) -> None:
  6. super().__init__(parent)
  7. self.resize(400,400)
  8. self.setWindowTitle('事件委托')
  9. self.laba = QLabel(self)
  10. self.laba.setText('I am Label A')
  11. font = self.laba.font()
  12. font.setPointSize(10)
  13. font.setBold(True)
  14. self.laba.setFont(font)
  15. self.laba.setGeometry(20,20,300,60)
  16. self.laba.installEventFilter(self)
  17. self.labb = QLabel(self)
  18. self.labb.setText('I am Label B')
  19. font = self.labb.font()
  20. font.setPointSize(10)
  21. font.setBold(True)
  22. self.labb.setFont(font)
  23. self.labb.setGeometry(20,100,300,60)
  24. self.labb.installEventFilter(self)
  25. def eventFilter(self, w, e) -> bool:
  26. if w == self.laba:
  27. if e.type()==QEvent.Enter:
  28. self.laba.setText('鼠标来啦')
  29. self.laba.setStyleSheet('background-color:rgb(170,255,255);')
  30. if e.type()==QEvent.Leave:
  31. self.laba.setText('I am Label A')
  32. self.laba.setStyleSheet('')
  33. if w == self.labb:
  34. if e.type()==QEvent.Enter:
  35. self.labb.setText('点我!')
  36. self.labb.setStyleSheet('background-color:rgb(85,255,127);')
  37. if e.type()==QEvent.MouseButtonPress:
  38. self.labb.setText('还真点啊!')
  39. self.labb.setStyleSheet('background-color:rgb(85,255,127);')
  40. if e.type()==QEvent.MouseButtonRelease:
  41. self.labb.setText('点我!')
  42. self.labb.setStyleSheet('background-color:rgb(85,255,127);')
  43. if e.type()==QEvent.Leave:
  44. self.labb.setText('I am Label B')
  45. self.labb.setStyleSheet('')
  46. return super().eventFilter(w, e)
  47. app = QApplication(sys.argv)
  48. form = QmyWidget()
  49. form.show()
  50. sys.exit(app.exec_())

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/897397
推荐阅读
相关标签
  

闽ICP备14008679号