Receiving pyqtSignal from Singleton

ぐ巨炮叔叔 提交于 2020-02-04 01:46:47

问题


There's singleton class in python:

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

The idea is to have one single data store accessible from allover the program. Every time a set Method is called, a signal should be emitted telling all instances that from somewhere the data was changed and should be re-read.

Cool plan, but if you look at the test code

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)

And the console output it get's strange (at least for me):

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

Both instances do have the same address, cool the singleton does it's job. To ds1 if've connected the "dataChange" signal which works properly if from ds1 data is updated. BUT no signal is received by ds1 if I change the data with ds2.set......

Does anybody have an explanation about what happens here. Data is shared properly across the instances, but not the signals:-/


回答1:


Although your Singleton class complies that the same object is always returned but that does not imply that it is correctly implemented, in your case in new the new object is created but you return the first object created (fulfilling what you apparently want) but the signal "dataChanged "belongs to the new object and not to the first object causing the problem. The solution in this case is to use metaclasses as this library points out:

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


来源:https://stackoverflow.com/questions/59459770/receiving-pyqtsignal-from-singleton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!