PyQt中的事件触发其实属于事件派发,接收到消息之后,分发给特定对象的event方法,event再进行具体的事件派发。而事件转发则是一个相反的过程,例如一个窗口A有一个空白控件B,控件里有一个标签C,如果点击标签C没有相关的处理,这个标签控件C会向父对象B进行转发,如果B也没有处理,则会向A转发事件。

正常的事件分发

# -*- coding: UTF-8 -*-
from PyQt5.Qt import *
import sys


class Window(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("顶层窗口鼠标被按下")


class MidWindow(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("中间的控件被按下")


class Label(QLabel):
    def mousePressEvent(self, QMouseEvent):
        print("标签控件鼠标按下")


# 创建一个应用
app = QApplication(sys.argv)
print(sys.argv)

# 创建一个QWidget类的窗口
window = Window()
window.setWindowTitle("事件转发")  # 标题W
window.resize(500, 500)  # 窗口的大小
window.move(400, 200)  # 窗口初次显示的位置

# 创建其他控件

mid_Window = MidWindow(window)
mid_Window.resize(300, 300)
mid_Window.setAttribute(Qt.WA_StyledBackground, True)   # 由于mid_Window继承于window,样式失效,需要设置一下
mid_Window.setStyleSheet("background-color: yellow;")

label = Label(mid_Window)
label.setText("这是一个标签")
label.setStyleSheet("background-color: red;")
label.move(100, 100)

window.show()  # 显示窗口,不然啥也没有

sys.exit(app.exec_())

没有问题

事件转发

上面三个都挺好的没有什么异常,纯粹普普通通的事件分发。

但是加入其中要是有一个没有可以处理的怎么办呢?于是寻思着注销掉一个重写的类:

我注销掉了label的类,再次点击标签

# -*- coding: UTF-8 -*-
from PyQt5.Qt import *
import sys


class Window(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("顶层窗口鼠标被按下")


class MidWindow(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("中间的控件被按下")


class Label(QLabel):
    # def mousePressEvent(self, QMouseEvent):
    #     print("标签控件鼠标按下")
    pass


# 创建一个应用
app = QApplication(sys.argv)
print(sys.argv)

# 创建一个QWidget类的窗口
window = Window()
window.setWindowTitle("事件转发")  # 标题W
window.resize(500, 500)  # 窗口的大小
window.move(400, 200)  # 窗口初次显示的位置

# 创建其他控件

mid_Window = MidWindow(window)
mid_Window.resize(300, 300)
mid_Window.setAttribute(Qt.WA_StyledBackground, True)   # 由于mid_Window继承于window,样式失效,需要设置一下
mid_Window.setStyleSheet("background-color: yellow;")

label = Label(mid_Window)
label.setText("这是一个标签")
label.setStyleSheet("background-color: red;")
label.move(100, 100)

window.show()  # 显示窗口,不然啥也没有

sys.exit(app.exec_())

事件的转发

同样的道理,加入把中间层的处理也注释了,那么点击标签,就会显示“顶层窗口鼠标被按下”,这里就不再演示。

如果使用按钮,就有不一样的效果,因为QPushButton自带着鼠标按下的事件。

ignore()和accept()

在Qt中,如果事件被ignore了,则事件会继续传播到上层,也就是执行事件转发。

accept则是表示这件事情自己处理了,不再往上转发,一般默认就是accept的,可以用isAccept()来检查。

# -*- coding: UTF-8 -*-
from PyQt5.Qt import *
import sys


class Window(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("顶层窗口鼠标被按下")


class MidWindow(QWidget):
    def mousePressEvent(self, QMouseEvent):
        print("中间的控件被按下")


class Label(QLabel):
    def mousePressEvent(self, QMouseEvent):
        print("标签控件鼠标按下")
        QMouseEvent.ignore()   # 事件假装没有被处理,继续往上层传


# 创建一个应用
app = QApplication(sys.argv)
print(sys.argv)

# 创建一个QWidget类的窗口
window = Window()
window.setWindowTitle("事件转发")  # 标题W
window.resize(500, 500)  # 窗口的大小
window.move(400, 200)  # 窗口初次显示的位置

# 创建其他控件

mid_Window = MidWindow(window)
mid_Window.resize(300, 300)
mid_Window.setAttribute(Qt.WA_StyledBackground, True)   # 由于mid_Window继承于window,样式失效,需要设置一下
mid_Window.setStyleSheet("background-color: yellow;")

label = Label(mid_Window)
label.setText("这是一个标签")
label.setStyleSheet("background-color: red;")
label.move(100, 100)

window.show()  # 显示窗口,不然啥也没有

sys.exit(app.exec_())

ignore


博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2022/shijianzhuanfa.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 07 月 16 日
如果觉得我的文章对你有用,请随意赞赏