1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
# This is a CamiTK python action
#
# FIXME Threads in Camitk Python Extensions do not work yet, action is disabled for now
# Test the interaction between python and the CamiTK application using 'self' and a thread.
# This is a simple test where a counter is incremented in the tick() method called by a
# thread that lives in Python.
# It demonstrates how state can be preserved using internal variables and a thread
#
# Click 'Start'/'Stop' to start/stop the timer. Note that the timer interval is slowed
# down/accelerated automatically within the tick() method.
# Note also that the parameter is set to 'read only' as a way to prove the internal
# self.counter increments properly.
import camitk
from PySide2.QtCore import QObject, QThread, pyqtSignal
class Worker(QObject):
finished = pyqtSignal()
ticked = pyqtSignal(int)
def __init__(self, counter:int, parent=None):
super().__init__(parent)
self.worker_counter = counter
self.stop_running = False
print(f"Worker counter: {self.worker_counter}")
def start_stop_worker(self):
self.stop_running = not self.stop_running
def run(self):
print(f"Running started with: {self.worker_counter}")
while True:
if not self.stop_running:
self.worker_counter += 1
print(f"Worker counter: {self.worker_counter}")
self.ticked.emit(self.worker_counter)
self.finished.emit()
def ticked(self, counter:int):
self.counter = counter
camitk.info(f"counter: {self.counter}")
# Backup state C++ memory is required as self.counter has changed in a
# method that is not called directly from C++ (init, process, targetDefined, parameterChanged),
# i.e., a function called from python by python.
# This is required to ensure the C++/python values are properly synchronized
self.saveState()
# update action (default) widget
self.updateWidget()
def init(self:camitk.Action):
self.worker = None
self.thread = None
self.running = False
self.setApplyButtonText("Start Thread")
class SignalProxy(QObject):
start_stop_worker = pyqtSignal()
def process(self:camitk.Action):
if not self.worker:
camitk.info("Creating Worker")
self.counter = 42
self.thread = QThread()
self.worker = Worker(self.counter)
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
self.worker.ticked.connect(lambda counter: ticked(self,counter))
camitk.info("Creating SignalProxy")
self.signal_proxy = SignalProxy()
self.signal_proxy.start_stop_worker.connect(self.worker.start_stop_worker)
camitk.info("After Creating SignalProxy")
self.thread.finished.connect(
lambda: camitk.info("Thread finished")
)
camitk.info("Starting Thread")
self.thread.start()
self.running = True
self.setApplyButtonText("Stop Thread")
else:
if self.running:
camitk.info("Stopping Thread")
# stop thread
self.signal_proxy.start_stop_worker.emit()
self.setApplyButtonText("Start Thread")
self.running = False
else:
self.signal_proxy.start_stop_worker.emit()
|