問題描述
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 Method 時,都應該發出一個信號,告訴所有實例數據從某個地方發生了更改,應該重新讀取.
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 類遵守始終返回相同的對象,但這并不意味著它已正確實現,在您的情況下,在 new 中創建了新對象但是您返回創建的第一個對象(滿足您顯然想要的)但信號dataChanged"屬于新對象而不是導致問題的第一個對象.這種情況下的解決方案是使用元類,因為這個庫指出:
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
這篇關于從 Singleton 接收 pyqtSignal的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!