我试图在PyQt中发出自定义事件。一个小部件将发出,另一个小部件将监听事件,但是两个小部件不需要关联。
在JavaScript中,我会这样做
// Component 1 document.addEventListener('Hello', () => console.log('Got it')) // Component 2 document.dispatchEvent(new Event("Hello"))
编辑:我知道信号和插槽,但只知道如何在父级和子级之间使用它们。我如何在任意不相关的小部件之间使用这种机制(或其他机制)?
在PyQt中,以下说明:
document.addEventListener('Hello', () => console.log('Got it'))
等价的
document.hello_signal.connect(lambda: print('Got it'))
以类似的方式:
document.dispatchEvent(new Event("Hello"))
document.hello_signal.emit()
但是最大的区别是“文档”对象的范围,因为连接是在全局元素之间。但是在PyQt中,该元素不存在。
模拟您指出的行为的一种方法是创建一个全局对象:
globalobject.py
from PyQt5 import QtCore import functools @functools.lru_cache() class GlobalObject(QtCore.QObject): def __init__(self): super().__init__() self._events = {} def addEventListener(self, name, func): if name not in self._events: self._events[name] = [func] else: self._events[name].append(func) def dispatchEvent(self, name): functions = self._events.get(name, []) for func in functions: QtCore.QTimer.singleShot(0, func)
main.py
from PyQt5 import QtCore, QtWidgets from globalobject import GlobalObject class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super().__init__(parent) button = QtWidgets.QPushButton(text="Press me", clicked=self.on_clicked) self.setCentralWidget(button) @QtCore.pyqtSlot() def on_clicked(self): GlobalObject().dispatchEvent("hello") class Widget(QtWidgets.QWidget): def __init__(self, parent=None): super().__init__(parent) GlobalObject().addEventListener("hello", self.foo) self._label = QtWidgets.QLabel() lay = QtWidgets.QVBoxLayout(self) lay.addWidget(self._label) @QtCore.pyqtSlot() def foo(self): self._label.setText("foo") if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) w1 = MainWindow() w2 = Widget() w1.show() w2.show() sys.exit(app.exec_())