从字典创建 pyqtSignals

Posted

技术标签:

【中文标题】从字典创建 pyqtSignals【英文标题】:Create pyqtSignals from dictionary 【发布时间】:2019-03-26 18:00:54 【问题描述】:

我正在编写一个通过 Python 设计的软件脚本,我将在 PyQt5 应用程序中过多地使用信号和插槽。我想到了创建一个字典,其中所有信号都进来,每个信号都有自己的键以便访问(或基本上将其连接到函数)。问题是我收到此错误 'AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute '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)

【问题讨论】:

【参考方案1】:

如docs中所示:

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

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

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_())

【讨论】:

这不是我真正想要的。我正在为仅初始化信号创建多个类而苦恼。我只想要一个类,我可以使用它来声明特定线程需要哪些信号或基本上是动态信号,就像我上面所做的那样。顺便感谢您及时回复。 @Mqtyx mmm,您希望同一类的对象具有不同的信号,因为目前这是不可能的(在 PyQt4 中,您可以创建信号,就好像它们是对象的属性一样),因为 PyQt5 需要它们被声明为类的属性(未绑定信号),因为在内部 SIP 将其转换为对象的属性(绑定信号)。所以你需要它,你不能。 知道了。我将继续创建信号的正常程序。感谢您的宝贵时间。

以上是关于从字典创建 pyqtSignals的主要内容,如果未能解决你的问题,请参考以下文章

Python:从字典格式的文本/文件创建字典

从 csv 文件创建字典?

从嵌套字典创建单个字典以更新 MySQLdb

从字典创建类实例?

从 json 数据值创建字典

如何从元组数组创建字典?