从 Singleton 接收 pyqtSignal

Receiving pyqtSignal from Singleton

python中有单例class:

from PyQt5.QtCore import QObject, pyqtSignal
import logging

class Singleton(QObject):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not isinstance(cls._instance, cls):
            cls._instance = QObject.__new__(cls, *args, **kwargs)
        return cls._instance


class DataStatus(Singleton, QObject):
    '''
    '''
    dataChanged = pyqtSignal(str)
    __val = 'init'

    def __init__(self):
        super().__init__()

    def setVal(self, val):
        self.dataChanged.emit('emit: ' + val)
        logging.debug('emit: ' + val)
        self.__val = val

    def getVal(self):
        return self.__val

这个想法是让整个程序都可以访问一个单一的数据存储。每次调用 set 方法时,都应发出一个信号,告诉所有实例数据已从某处更改并应重新读取。

很酷的计划,但是如果你看看测试代码

def test(self):     
    self.ds1 = DataStatus()
    self.ds1.dataChanged.connect(self.windowaction)
    print(self.ds1)
    print(self.ds1.getVal())

    self.ds1.setVal('ds1.first')

    self.ds2 = DataStatus()
    #self.ds2.dataChanged.connect(self.windowaction)
    print(self.ds2)
    print(self.ds2.getVal())

    self.ds2.setVal('ds2.second')

    print(self.ds1.getVal())

def windowaction(self, q):
    print(q)

控制台输出很奇怪(至少对我而言):

<DataStatus.DataStatus.DataStatus object at 0x03207580>
init
emit: ds1.first
<DataStatus.DataStatus.DataStatus object at 0x03207580>
ds1.first
ds2.second

两个实例确实有相同的地址,很酷的单身人士完成了它的工作。 如果已连接 "dataChange" 信号到 ds1,如果来自 ds1 的数据已更新,该信号将正常工作。 但是如果我用 ds2.set......

更改数据,则 ds1 不会收到任何信号

有人对这里发生的事情有解释吗?数据在实例之间正确共享,但信号不是:-/

尽管您的单例 class 遵守始终 returned 相同的对象,但这并不意味着它已正确实现,在您的情况下,新对象已创建,但您 return 创建的第一个对象(满足您显然想要的)但信号 "dataChanged " 属于新对象而不属于引起问题的第一个对象。这种情况下的解决方案是使用 metaclasses this library 指出:

class Singleton(type(QObject), type):
    def __init__(cls, name, bases, dict):
        super().__init__(name, bases, dict)
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance


class DataStatus(QObject, metaclass=Singleton):
    dataChanged = pyqtSignal(str)
    __val = "init"

    def __init__(self):
        super().__init__()

    def setVal(self, val):
        self.dataChanged.emit("emit: " + val)
        logging.debug("emit: " + val)
        self.__val = val

    def getVal(self):
        return self.__val