从单例接收 pyqtSignal [英] Receiving pyqtSignal from Singleton

查看:127
本文介绍了从单例接收 pyqtSignal的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

python 中有单例类:

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

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

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

两个实例都有相同的地址,很酷的单身人士做它的工作.到 ds1 如果已经连接了dataChange"信号,如果来自 ds1 的数据被更新,该信号可以正常工作.但是如果我用 ds2.set 更改数据,ds1 没有收到任何信号......

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:-/

推荐答案

虽然你的 Singleton 类遵守总是返回相同的对象,但这并不意味着它被正确实现,在你的情况下,新对象被创建但是您返回创建的第一个对象(满足您显然想要的),但信号dataChanged"属于新对象,而不是导致问题的第一个对象.在这种情况下的解决方案是使用元类作为 this library 指出:

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

这篇关于从单例接收 pyqtSignal的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆