I have a thread which produces some data (a python list) and which shall be available for a widget that will read and display the data in the main thread. Actually, I'm using QMutex to provide access to the data, in this way:
class Thread(QThread):
def get_data(self):
QMutexLock(self.mutex)
return deepcopy(self.data)
def set_data(self, data):
QMutexLock(self.mutex)
self.data = deepcopy(data)
def run(self):
self.mutex = QMutex()
while True:
self.data = slowly_produce_data()
self.emit(SIGNAL("dataReady()"))
class Widget(QWidget):
def __init__(self):
self.thread = Thread()
self.connect(self.thread, SIGNAL("dataReady()"), self.get_data)
self.thread.start()
def get_data(self):
self.data = self.thread.get_data()
def paintEvent(self, event):
paint_somehow(self.data)
Note that I'm not passing the data in the emit()
as they are generic data (I tried to use PyObject as data type, but a double free()
would crash the program), but I'm copying the data with a deepcopy()
(assuming the data can be copied like this).
I used a deepcopy() because I guess that a code like:
def get_data(self):
QMutexLock(self.mutex)
return self.data
would only copy a reference to the data (right?) and data would be shared AND unlocked after the return... Is this code correct? What can I do if data are really large (like a list of 1'000'000 items)?
Thanks.
P.S. I saw some examples, like the Qt Mandelbrot example, or the threading example with PyQt, but they use QImage as parameter in the slots.
I think this should work with PySide. if not work please report a bug on PySide bugzilla(http://bugs.openbossa.org/) with a small test case:
class Thread(QThread):
dataReady = Signal(object)
def run(self):
while True:
self.data = slowly_produce_data()
# this will add a ref to self.data and avoid the destruction
self.dataReady.emit(self.data)
class Widget(QWidget):
def __init__(self):
self.thread = Thread()
self.thread.dataReady.connect(self.get_data, Qt.QueuedConnection)
self.thread.start()
def get_data(self, data):
self.data = data
def paintEvent(self, event):
paint_somehow(self.data)