从字典创建pyqtSignals

问题描述 投票:1回答:1

好吧,我正在编写一个通过Python设计的软件,我将在PyQt5应用程序中使用信号和插槽。我想到了创建一个字典,其中所有信号都进入,每个信号都有自己的密钥以便访问(或基本上将它连接到一个函数)。问题是我得到这个错误'AttributeError:'PyQt5.QtCore.pyqtSignal'对象由于某种原因没有属性'connect'。我读到了这个错误并发现我必须在构造函数之外声明信号以使其工作但不幸的是,这会破坏我的想法,所以,我来到这里,所以有人可以解决我的问题。

如果你仍然不明白,这是代码:

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QRunnable, pyqtSlot, QThreadPool, QObject, pyqtSignal

class WorkerSignals(QObject):
    signals = {}

    def __init__(self, **kwargs):
        QObject.__init__(self)
        if (kwargs is not None):
            for key, value in kwargs.items():
                self.signals[key] = value

class Worker(QRunnable):
    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):
        self.fn(*self.args, **self.kwargs)

以及创建信号的示例:

worker_signals = WorkerSignals(result=pyqtSignal(str), error=pyqtSignal(str))
worker_signals.signals['result'].connect(self.on_receive_result)
worker_signals.signals['error'].connect(self.on_receive_error)
python pyqt pyqt5 qt-signals qobject
1个回答
2
投票

docs所示:

信号(特别是未绑定信号)是类属性。当信号被引用为类的实例的属性时,PyQt5自动将实例绑定到信号以便创建绑定信号。 [...]

因此,它不仅必须在构造函数之外声明,而且必须是静态属性,因为它用作创建属于该实例的信号的原型。一种可能的解决方案是使用type来创建动态类:

from PyQt5 import QtCore

d = {
    "result": QtCore.pyqtSignal(str),
    "error": QtCore.pyqtSignal(str)
}

WorkerSignals = type("WorkerSignals", (QtCore.QObject,), d)

if __name__ == '__main__':
    import sys
    app = QtCore.QCoreApplication(sys.argv)
    worker_signals = WorkerSignals()

    def on_result(text):
        print("result:", text)

    def on_error(text):
        print("error:", text)

    worker_signals.result.connect(on_result)
    worker_signals.error.connect(on_error)

    def emit_result():
        worker_signals.result.emit(" 1+1=2 ")
    def emit_error():
        worker_signals.error.emit(" :( ")

    QtCore.QTimer.singleShot(1000, emit_result)
    QtCore.QTimer.singleShot(2000, emit_error)

    QtCore.QTimer.singleShot(3000, app.quit)
    sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.