eventFilter python demo
一般网上能找到大量的c++
代码关于过滤事件的例子,这里给一个简单完整的python PyQt5 的eventFilter
例子,例子的代码原本是Qt4 来自于 https://stackoverflow.com/questions/28050397/eventfilter-on-a-qwidget-with-pyqt4 ,但是现在似乎都不怎么用QT4了,所以我稍微改了一下,变成Qt5使用 。(如有侵code 删)
完整代码如下:
xxxxxvm16$ cat eventF2.py
#!/usr/bin/env python
# coding=utf-8
import sys
import random
import time
from PyQt5 import QtGui, QtCore
#from PyQt5.QtGui import *
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QVBoxLayout, QPushButton
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.__setUI()
def __setUI(self, appTitle="[default title]"):
self.statusBar()
mainWidget = QWidget()
vbox = QVBoxLayout()
button = QPushButton("Hello")
vbox.addWidget( button )
points = DrawingPointsWidget()
vbox.addWidget(points)
mainWidget.setLayout(vbox)
self.setCentralWidget(mainWidget)
#self.installEventFilter(self)
points.installEventFilter(self)
button.installEventFilter(points) ##new_added
def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.MouseMove: #if event.type() == QtCore.QEvent.HoverMove:
mousePosition = event.pos()
cursor = QtGui.QCursor()
self.statusBar().showMessage(
"Mouse: [" + mousePosition.x().__str__() + ", " + mousePosition.y().__str__() + "]"
+ "\tCursor: [" + cursor.pos().x().__str__() + ", " + cursor.pos().y().__str__() + "]"
)
print("MouseMove obj: %s, self: %s"%(object, self))
return True
elif event.type() == QtCore.QEvent.MouseButtonPress:
print("Mouse pressed obj: %s, self: %s"%(object, self))
print("dir(self): %s"%dir(self))
return True
return False
class DrawingPointsWidget(QWidget):
""
def __init__(self):
super(QWidget, self).__init__()
self.setMouseTracking(True)
self.__setUI()
def __setUI(self):
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Points')
self.show()
def paintEvent(self, e):
"Re-implemented method"
print("paintEvent self: %s, e: %s"%(self, e))
qp = QtGui.QPainter()
qp.begin(self)
self.drawPoints(qp)
qp.end()
def drawPoints(self, qp):
qp.setPen(QtCore.Qt.red)
"Need to get the size in case the window is resized -> generates a new paint event"
size = self.size()
for i in range(1000):
x = random.randint(1, size.width()-1 )
y = random.randint(1, size.height()-1 )
qp.drawPoint(x, y)
def eventFilter(self, obj, ev):
#print("DrawingPointsWidget self: %s"%self)
#time.sleep(1)
if ev.type() == QtCore.QEvent.MouseButtonPress:
print("self: %s, obj: %s, ev: %s,"%(self, obj, ev))
return True
return False
def main():
app = QApplication(sys.argv)
#window = WidgetsWindow2()
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
关键的部分在于下面这一部分:
#self.installEventFilter(self)
points.installEventFilter(self)
button.installEventFilter(points) ##new_added !!!
注意一下几个要点:
- 事件筛选器需要由要监视的对象设置
points.installEventFilter(self) 要监视的对象是谁?points
只有在 points 控件区域 移动鼠标 才会不断在状态栏 更新坐标
这里的self
是干啥的??? 在这里当然是指 self: <__main__.MainWindow object at 0x7fa210a79ca8>
主窗口控件对象
这个代码表明我们只能在 points
区域去点鼠标才会在控制台输出Mouse pressed
.
现在我们来解读 button.installEventFilter(points)
这是一个很奇怪的操作,最终导致我们点击button
hello 会在控制台打印内容
self: <__main__.DrawingPointsWidget object at 0x7f4aa18e6f78>, obj: <PyQt5.QtWidgets.QPushButton object at 0x7f4aa18e6ca8>, ev: <PyQt5.QtGui.QMouseEvent object at 0x7f4a9a0a61f8>
疑问的当然是button.installEventFilter(points)
中的points
,讲道理pointer
所代表的控件和 button
控件是分开的,为什么依然发生了这种过滤行为 。
如果我们把代码改一下,改成button.installEventFilter(self) #button.installEventFilter(points)
Mouse pressed obj: <__main__.DrawingPointsWidget object at 0x7f3fe635ef78>, self: <__main__.MainWindow object at 0x7f3fe635edc8>
Mouse pressed obj: <PyQt5.QtWidgets.QPushButton object at 0x7f3fe635ee58>, self: <__main__.MainWindow object at 0x7f3fe635edc8>
暂时先这样理解:
button.installEventFilter(points)
安装这个过滤事件,可以认为是 points
这个控件,也就是说被监控的控件是button
,当被监控的控件出现被过过滤的行为的时候,会触发points
这个控件里面定义的eventFilter
函数 。
可以借助 这篇文章 来理解 其中关系 https://blog.csdn.net/m0_37329910/article/details/88089582