I am building a PySide2 GUI that, among other things, reads out a camera module.
I try to read out a camera object in a separate thread. The camera is waiting for a hardware trigger given by the user. This can take up to 5 min, the GUI should be blocked.
The solution I try to implement: Move the action of waiting for the camera image to another thread.
The problem: Thread does not start due to error: '__init__' method of object's base class not called
The class to read out the Camera:
The debug print in __init__ is called.
class CameraWorker(QObject):
image_value = Signal(np.ndarray)
finished = Signal()
def __init__(self, hardware_trigger : bool, camera):
"""
CameraWorker:
Try to read out MyCamera class
Parameters
----------
hardware_trigger : bool
Define if the camera is waiting for a hardware trigger or if the camera will by triggered by the software call
camera : MyCamera
Camera object
"""
super().__init__()
logger.debug('construct worker')
self.camera = camera
self.hardware_trigger = hardware_trigger
def run(self):
"""
Run CameraWorker to read out the image feedback of the camera
"""
logger.info('run CameraWorker')
# hardware trigger True: wait for image - Otherwise the image is sent back now
i = self.camera._MyCamera__snap_image(close=False, hardware_trigger=self.hardware_trigger)
# Return image value
self.image_value.emit(i)
self.finished.emit()
The PySide2 app intended to call this:
class Main_Window(QMainWindow):
def __init__(self):
"""Initiate a new QT window based on the ui documents in folder ui_interface
"""
super(Main_Window, self).__init__()
self.ui = Ui_MainWindow()
[...] more code
def capture_image(self):
"""
Capture one image. When in Hardware mode, the camera is instructed to wait for the TTL signal for max 5 min
"""
def assign_image(i):
self.image = i
print('Image captured')
Thread(target=self.save_image(), args =self).start()
self.display_image()
hardware_trigger = True if self.ui.select_trigger_main.currentText() == 'Hardware trigger' else False
# Step 2: Create a QThread object
self.thread = QThread()
# Step 3: Create a worker object
self.worker = CameraWorker(hardware_trigger=hardware_trigger, camera=self.camera)
# Step 4: Move worker to the thread
self.worker.moveToThread(self.thread)
# Step 5: Connect signals and slots
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.finished.connect(self.capture_image)
self.worker.image_value.connect(assign_image)
# Step 6: Start the thread
logger.debug("Ready to capture image")
self.thread.start()
Note: This code is based on this post.