File: test_self_interaction_thread_tentative.py

package info (click to toggle)
camitk 6.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 389,496 kB
  • sloc: cpp: 103,476; sh: 2,448; python: 1,618; xml: 984; makefile: 128; perl: 84; sed: 20
file content (96 lines) | stat: -rw-r--r-- 3,542 bytes parent folder | download
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()