Python PyQT中的绑定事件处理程序

Python PyQT中的绑定事件处理程序,python,events,pyqt5,Python,Events,Pyqt5,使用PyQt5,我可以将某些事件处理程序绑定到我的对象,而其他事件处理程序只有在我将它们作为方法实现时才能工作。changeEvent和event是后一种类型的示例 在我下面的示例中,您可以看到我可以通过编程方式将keyPressEvent处理程序添加到我的小部件中,但我不能对changeEvent执行相同的操作 是什么让changeEvent与众不同?如何强制它按我所希望的方式运行?使用setattr重写方法是一个不好的选择,因为它不是很优雅,如果您想要侦听另一个QWidget的事件,那么最好

使用PyQt5,我可以将某些事件处理程序绑定到我的对象,而其他事件处理程序只有在我将它们作为方法实现时才能工作。changeEvent和event是后一种类型的示例

在我下面的示例中,您可以看到我可以通过编程方式将keyPressEvent处理程序添加到我的小部件中,但我不能对changeEvent执行相同的操作


是什么让changeEvent与众不同?如何强制它按我所希望的方式运行?

使用setattr重写方法是一个不好的选择,因为它不是很优雅,如果您想要侦听另一个QWidget的事件,那么最好使用事件过滤器

from PyQt5 import QtGui, QtWidgets, QtCore


class Binder(QtCore.QObject):
    def __init__(self, qobject):
        super().__init__(qobject)
        self._qobject = qobject
        self.qobject.installEventFilter(self)

    @property
    def qobject(self):
        return self._qobject

    def eventFilter(self, obj, event):
        if self.qobject is obj:
            print(event.type(), event)

        return super().eventFilter(obj, event)


class My_Widget(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("w1")
        Binder(self)


class My_Widget2(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("w2")


app = QtWidgets.QApplication([])
mw1 = My_Widget()
mw1.show()
mw2 = My_Widget2()
mw2.show()
app.exec_()

另一方面,没有文档记录哪些方法可以分配或不分配,因此如果您想找到原因,必须分析sip和pyqt5的源代码。需要指出的是,PyQt5创建了一个方法缓存(不知道缓存中存储了什么方法或什么方法)。

我认为eventFilter有点不受欢迎,因为它可能会对每个事件造成性能影响。我并不是在试图监听其他小部件的事件,只是试图在不使用多重继承的情况下将相同的功能添加到许多不同类型的小部件中。此外,我之所以使用这种绑定方法,是因为我想在两个类上都使用它,我不想限制继承的共享依赖性
from PyQt5 import QtGui, QtWidgets, QtCore


class Binder(QtCore.QObject):
    def __init__(self, qobject):
        super().__init__(qobject)
        self._qobject = qobject
        self.qobject.installEventFilter(self)

    @property
    def qobject(self):
        return self._qobject

    def eventFilter(self, obj, event):
        if self.qobject is obj:
            print(event.type(), event)

        return super().eventFilter(obj, event)


class My_Widget(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("w1")
        Binder(self)


class My_Widget2(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("w2")


app = QtWidgets.QApplication([])
mw1 = My_Widget()
mw1.show()
mw2 = My_Widget2()
mw2.show()
app.exec_()