简体   繁体   English

如何在 PyQt 中向事件循环发出自定义事件

[英]How to emit custom Events to the Event Loop in PyQt

I am trying to emit custom events in PyQt.我正在尝试在 PyQt 中发出自定义事件。 One widget would emit and another would listen to events, but the two widgets would not need to be related.一个小部件将发出,另一个将侦听事件,但这两个小部件不需要相关联。

In JavaScript, I would achieve this by doing在 JavaScript 中,我会通过这样做来实现这一点

// Component 1
document.addEventListener('Hello', () => console.log('Got it'))

// Component 2
document.dispatchEvent(new Event("Hello"))

Edit: I know about signals and slots, but only know how to use them between parent and child.编辑:我知道信号和插槽,但只知道如何在父子之间使用它们。 How would I this mechanism (or other mechanism) between arbitrary unrelated widgets?我将如何在任意不相关的小部件之间使用这种机制(或其他机制)?

In PyQt the following instruction:在 PyQt 中,以下指令:

document.addEventListener('Hello', () => console.log('Got it'))

is equivalent是等价的

document.hello_signal.connect(lambda: print('Got it'))

In a similar way:以类似的方式:

document.dispatchEvent(new Event("Hello"))

is equivalent是等价的

document.hello_signal.emit()

But the big difference is the scope of the "document" object, since the connection is between a global element.但最大的区别是“文档”对象的范围,因为连接是在一个全局元素之间。 But in PyQt that element does not exist.但是在 PyQt 中该元素不存在。

One way to emulate the behavior that you point out is by creating a global object:模拟您指出的行为的一种方法是创建一个全局对象:

globalobject.py全局对象.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_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM