pre local llm test
This commit is contained in:
+386
-22
@@ -26,6 +26,7 @@ from PyQt6.QtWidgets import (
|
||||
ROOT = Path(__file__).parent
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from hardware.helios_laser import HeliosLaser
|
||||
from hardware.pybbd202 import AXIS_X, AXIS_Y, ThorlabsServoDriver
|
||||
from hardware.tektronix_base import TektronixOscilloscopeBase
|
||||
from hardware.uc480_camera import CameraStreamThread, UC480Camera
|
||||
@@ -34,11 +35,12 @@ from hardware.uc480_camera import CameraStreamThread, UC480Camera
|
||||
|
||||
_AUI_DEFAULTS_PATH = ROOT / "aui_defaults.json"
|
||||
_AUI_DEFAULTS_FALLBACK = {
|
||||
"t3r_port": "/dev/ttyUSB0",
|
||||
"bbd_port": "/dev/ttyUSB1",
|
||||
"oscope_ip": "192.168.0.1",
|
||||
"t3r_port": "/dev/ttyUSB0",
|
||||
"bbd_port": "/dev/ttyUSB1",
|
||||
"oscope_ip": "192.168.0.1",
|
||||
"laser_freq_hz": 2000,
|
||||
"save_dir": str(ROOT / "scans"),
|
||||
"save_dir": str(ROOT / "scans"),
|
||||
"helios_port": "/dev/ttyUSB2",
|
||||
}
|
||||
|
||||
def _load_aui_defaults() -> dict:
|
||||
@@ -66,6 +68,7 @@ DEFAULT_BBD_PORT = _aui["bbd_port"]
|
||||
DEFAULT_OSCOPE_IP = _aui["oscope_ip"]
|
||||
DEFAULT_LASER_FREQ_HZ = float(_aui["laser_freq_hz"])
|
||||
DEFAULT_SAVE_DIR = _aui["save_dir"]
|
||||
DEFAULT_HELIOS_PORT = _aui.get("helios_port", "/dev/ttyUSB2")
|
||||
|
||||
# ── Scan constants ───────────────────────────────────────────────────────────
|
||||
|
||||
@@ -512,7 +515,7 @@ class OscopeWorker(QObject):
|
||||
|
||||
# ── CH1 — RF Acoustic Packet ──────────────────────────────────────────
|
||||
s.set_channel_label_name(1, "RF Acoustic Packet")
|
||||
s.set_channel_scale(1, 0.05) # 100 mV/div
|
||||
s.set_channel_scale(1, 0.07) # 70 mV/div
|
||||
s.set_channel_position(1, 0.0) # 0 divs
|
||||
s.set_channel_termination(1, 50) # 50 Ohm
|
||||
s.set_channel_coupling(1, "DC")
|
||||
@@ -536,7 +539,7 @@ class OscopeWorker(QObject):
|
||||
|
||||
# ── CH4 — Bias B ──────────────────────────────────────────────────────
|
||||
s.set_channel_label_name(4, "Bias - B")
|
||||
s.set_channel_scale(4, 0.1) # 50 mV/div
|
||||
s.set_channel_scale(4, 0.1) # 100 mV/div
|
||||
s.set_channel_position(4, -2.72) # -2.72 divs
|
||||
s.set_channel_termination(4, 1000000) # 1 Mohm
|
||||
s.set_channel_coupling(4, "DC")
|
||||
@@ -562,11 +565,167 @@ class OscopeWorker(QObject):
|
||||
self._cmd_q.put({"type": "stop"})
|
||||
|
||||
|
||||
# ── Helios laser worker ───────────────────────────────────────────────────────
|
||||
|
||||
class HeliosWorker(QObject):
|
||||
"""Manages HeliosLaser in a worker thread using a command queue."""
|
||||
connected = pyqtSignal()
|
||||
disconnected = pyqtSignal()
|
||||
connection_failed = pyqtSignal(str)
|
||||
enabled_updated = pyqtSignal(bool)
|
||||
current_updated = pyqtSignal(int)
|
||||
diode_temp_updated = pyqtSignal(float)
|
||||
pstage_temp_updated = pyqtSignal(float)
|
||||
qswitch_temp_updated = pyqtSignal(float)
|
||||
status_registers_updated = pyqtSignal(object, object, object) # LER, LCE, CCE (int|None)
|
||||
error_occurred = pyqtSignal(str)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._laser: HeliosLaser | None = None
|
||||
self._cmd_q: queue.Queue = queue.Queue()
|
||||
self._running = False
|
||||
self.is_connected = False
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self):
|
||||
self._running = True
|
||||
while self._running:
|
||||
try:
|
||||
cmd = self._cmd_q.get(timeout=0.1)
|
||||
self._dispatch(cmd)
|
||||
except queue.Empty:
|
||||
pass
|
||||
if self._laser:
|
||||
try:
|
||||
self._laser.disconnect()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _dispatch(self, cmd: dict):
|
||||
t = cmd["type"]
|
||||
if t == "connect":
|
||||
self._do_connect(cmd["port"])
|
||||
elif t == "disconnect":
|
||||
self._do_disconnect()
|
||||
elif t == "set_enable":
|
||||
self._do_set_enable(cmd["enable"])
|
||||
elif t == "set_current":
|
||||
self._do_set_current(cmd["current_ma"])
|
||||
elif t == "poll_status":
|
||||
self._do_poll_status()
|
||||
elif t == "stop":
|
||||
self._running = False
|
||||
|
||||
def _do_connect(self, port: str):
|
||||
try:
|
||||
self._laser = HeliosLaser(timeout=1.0)
|
||||
if not self._laser.connect(port):
|
||||
self._laser = None
|
||||
self.connection_failed.emit("Failed to open serial port")
|
||||
return
|
||||
self.is_connected = True
|
||||
self.connected.emit()
|
||||
self._do_poll_status()
|
||||
except Exception as e:
|
||||
self._laser = None
|
||||
self.connection_failed.emit(str(e))
|
||||
|
||||
def _do_disconnect(self):
|
||||
if self._laser:
|
||||
try:
|
||||
self._laser.set_laser_enable(False)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self._laser.disconnect()
|
||||
except Exception:
|
||||
pass
|
||||
self._laser = None
|
||||
self.is_connected = False
|
||||
self.disconnected.emit()
|
||||
|
||||
def _do_set_enable(self, enable: bool):
|
||||
if not self._laser:
|
||||
return
|
||||
try:
|
||||
self._laser.set_laser_enable(enable)
|
||||
self.enabled_updated.emit(self._laser.is_laser_enabled())
|
||||
except Exception as e:
|
||||
self.error_occurred.emit(str(e))
|
||||
|
||||
def _do_set_current(self, current_ma: int):
|
||||
if not self._laser:
|
||||
return
|
||||
try:
|
||||
self._laser.set_current_ma(current_ma)
|
||||
self.current_updated.emit(current_ma)
|
||||
except Exception as e:
|
||||
self.error_occurred.emit(str(e))
|
||||
|
||||
def _do_poll_status(self):
|
||||
if not self._laser or not self._laser.is_connected:
|
||||
return
|
||||
try:
|
||||
ler, lce, cce = self._laser.get_status_registers()
|
||||
self.status_registers_updated.emit(ler, lce, cce)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.enabled_updated.emit(self._laser.is_laser_enabled())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
current = self._laser.get_current_ma()
|
||||
if current is not None:
|
||||
self.current_updated.emit(current)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
t = self._laser.get_diode_temp_c()
|
||||
if t is not None:
|
||||
self.diode_temp_updated.emit(t)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
t = self._laser.get_power_stage_temp_c()
|
||||
if t is not None:
|
||||
self.pstage_temp_updated.emit(t)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
t = self._laser.get_qswitch_temp_c()
|
||||
if t is not None:
|
||||
self.qswitch_temp_updated.emit(t)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def queue_connect(self, port: str):
|
||||
self._cmd_q.put({"type": "connect", "port": port})
|
||||
|
||||
def queue_disconnect(self):
|
||||
self._cmd_q.put({"type": "disconnect"})
|
||||
|
||||
def queue_set_enable(self, enable: bool):
|
||||
self._cmd_q.put({"type": "set_enable", "enable": enable})
|
||||
|
||||
def queue_set_current(self, current_ma: int):
|
||||
self._cmd_q.put({"type": "set_current", "current_ma": current_ma})
|
||||
|
||||
def queue_poll_status(self):
|
||||
self._cmd_q.put({"type": "poll_status"})
|
||||
|
||||
def stop_worker(self):
|
||||
self._cmd_q.put({"type": "stop"})
|
||||
|
||||
|
||||
# ── Camera window popup ───────────────────────────────────────────────────────
|
||||
|
||||
class CameraWindow(QWidget):
|
||||
"""Camera display popup — auto-connects on show, auto-disconnects on close."""
|
||||
|
||||
closed = pyqtSignal()
|
||||
|
||||
def __init__(self, parent: QWidget | None = None):
|
||||
super().__init__(parent, Qt.WindowType.Window)
|
||||
uic.loadUi(ROOT / "sc3-aui-camera.ui", self)
|
||||
@@ -590,18 +749,25 @@ class CameraWindow(QWidget):
|
||||
|
||||
self.uc480_exposure_slider.valueChanged.connect(self._set_exposure)
|
||||
self.uc480_gain_slider.valueChanged.connect(self._set_gain)
|
||||
self.uc480_start_btn.clicked.connect(self._start_stream)
|
||||
self.uc480_stop_btn.clicked.connect(self._stop_stream)
|
||||
self.uc480_close_window_btn.clicked.connect(self.close)
|
||||
|
||||
self._update_controls()
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
self._start_camera()
|
||||
self._connect_camera()
|
||||
self._start_stream()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self._stop_camera()
|
||||
self._stop_stream()
|
||||
self._disconnect_camera()
|
||||
super().closeEvent(event)
|
||||
self.closed.emit()
|
||||
|
||||
def _start_camera(self):
|
||||
if self._stream is not None:
|
||||
def _connect_camera(self):
|
||||
if self._camera is not None:
|
||||
return
|
||||
try:
|
||||
self._camera = UC480Camera()
|
||||
@@ -610,22 +776,33 @@ class CameraWindow(QWidget):
|
||||
self.uc480_exposure_slider.blockSignals(True)
|
||||
self.uc480_exposure_slider.setValue(max(1, round(exp_ms * 10)))
|
||||
self.uc480_exposure_slider.blockSignals(False)
|
||||
self._stream = CameraStreamThread(self._camera)
|
||||
self._stream.frame_ready.connect(self._on_frame)
|
||||
self._stream.start()
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Camera Error", f"Could not open camera:\n{e}")
|
||||
self._camera = None
|
||||
self._frame_label.setText(f"Camera error:\n{e}")
|
||||
self._update_controls()
|
||||
|
||||
def _stop_camera(self):
|
||||
if self._stream:
|
||||
self._stream.stop()
|
||||
self._stream = None
|
||||
def _disconnect_camera(self):
|
||||
if self._camera:
|
||||
try:
|
||||
self._camera.cleanup()
|
||||
except Exception:
|
||||
pass
|
||||
self._camera = None
|
||||
self._update_controls()
|
||||
|
||||
def _start_stream(self):
|
||||
if self._stream is not None or self._camera is None:
|
||||
return
|
||||
self._stream = CameraStreamThread(self._camera)
|
||||
self._stream.frame_ready.connect(self._on_frame)
|
||||
self._stream.start()
|
||||
self._update_controls()
|
||||
|
||||
def _stop_stream(self):
|
||||
if self._stream:
|
||||
self._stream.stop()
|
||||
self._stream = None
|
||||
self._update_controls()
|
||||
|
||||
def _on_frame(self, image: QImage):
|
||||
px = QPixmap.fromImage(image).scaled(
|
||||
@@ -650,6 +827,162 @@ class CameraWindow(QWidget):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _update_controls(self):
|
||||
camera_ok = self._camera is not None
|
||||
streaming = self._stream is not None
|
||||
self.uc480_start_btn.setEnabled(camera_ok and not streaming)
|
||||
self.uc480_stop_btn.setEnabled(streaming)
|
||||
self.uc480_exposure_slider.setEnabled(camera_ok)
|
||||
self.uc480_gain_slider.setEnabled(camera_ok)
|
||||
|
||||
|
||||
# ── Helios laser panel ────────────────────────────────────────────────────────
|
||||
|
||||
class HeliosWindow(QWidget):
|
||||
"""Helios laser control panel — shown/hidden with a toggle in the main window."""
|
||||
|
||||
closed = pyqtSignal()
|
||||
|
||||
def __init__(self, worker: HeliosWorker, parent: QWidget | None = None):
|
||||
super().__init__(parent, Qt.WindowType.Window)
|
||||
uic.loadUi(ROOT / "sc3-aui-helios.ui", self)
|
||||
self.setWindowTitle("Helios Laser")
|
||||
|
||||
self._worker = worker
|
||||
|
||||
self._poll_timer = QTimer(self)
|
||||
self._poll_timer.setInterval(1000)
|
||||
self._poll_timer.timeout.connect(self._worker.queue_poll_status)
|
||||
|
||||
self._wire_signals()
|
||||
self._update_controls(False)
|
||||
self._set_emission_indicator(False)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self._poll_timer.stop()
|
||||
if self._worker.is_connected:
|
||||
self._worker.queue_disconnect()
|
||||
super().closeEvent(event)
|
||||
self.closed.emit()
|
||||
|
||||
def _wire_signals(self):
|
||||
self.helios_connect_toggle.toggled.connect(self._on_connect_toggle)
|
||||
self._worker.connected.connect(self._on_connected)
|
||||
self._worker.disconnected.connect(self._on_disconnected)
|
||||
self._worker.connection_failed.connect(self._on_connection_failed)
|
||||
|
||||
self.helios_enable_btn.toggled.connect(self._on_enable_toggle)
|
||||
self._worker.enabled_updated.connect(self._on_enabled_updated)
|
||||
|
||||
self.helios_set_current_btn.clicked.connect(self._on_set_current)
|
||||
self._worker.current_updated.connect(self._on_current_updated)
|
||||
self._worker.diode_temp_updated.connect(
|
||||
lambda t: self.helios_temp_diode_label.setText(f"{t:.1f} °C")
|
||||
)
|
||||
self._worker.pstage_temp_updated.connect(
|
||||
lambda t: self.helios_temp_pstage_label.setText(f"{t:.1f} °C")
|
||||
)
|
||||
self._worker.qswitch_temp_updated.connect(
|
||||
lambda t: self.helios_temp_qswitch_label.setText(f"{t:.1f} °C")
|
||||
)
|
||||
self._worker.status_registers_updated.connect(self._on_status_registers)
|
||||
self._worker.error_occurred.connect(
|
||||
lambda m: self.helios_status_label.setText(m)
|
||||
)
|
||||
|
||||
def _on_connect_toggle(self, checked: bool):
|
||||
if checked:
|
||||
self.helios_connect_toggle.setText("Connecting…")
|
||||
self.helios_connect_toggle.setEnabled(False)
|
||||
port = self.helios_port_edit.text().strip()
|
||||
d = _load_aui_defaults()
|
||||
d["helios_port"] = port
|
||||
_save_aui_defaults(d)
|
||||
self._worker.queue_connect(port)
|
||||
else:
|
||||
self._poll_timer.stop()
|
||||
self._worker.queue_disconnect()
|
||||
|
||||
def _on_connected(self):
|
||||
self.helios_connect_toggle.setEnabled(True)
|
||||
self.helios_connect_toggle.setText("Disconnect")
|
||||
self.helios_status_label.setText("Connected")
|
||||
self._update_controls(True)
|
||||
self._poll_timer.start()
|
||||
|
||||
def _on_disconnected(self):
|
||||
self._poll_timer.stop()
|
||||
self.helios_connect_toggle.blockSignals(True)
|
||||
self.helios_connect_toggle.setChecked(False)
|
||||
self.helios_connect_toggle.setText("Connect")
|
||||
self.helios_connect_toggle.setEnabled(True)
|
||||
self.helios_connect_toggle.blockSignals(False)
|
||||
self.helios_status_label.setText("Disconnected")
|
||||
self._update_controls(False)
|
||||
|
||||
def _on_connection_failed(self, msg: str):
|
||||
self.helios_connect_toggle.blockSignals(True)
|
||||
self.helios_connect_toggle.setChecked(False)
|
||||
self.helios_connect_toggle.setText("Connect")
|
||||
self.helios_connect_toggle.setEnabled(True)
|
||||
self.helios_connect_toggle.blockSignals(False)
|
||||
self.helios_status_label.setText(f"Failed: {msg}")
|
||||
self._update_controls(False)
|
||||
|
||||
def _set_emission_indicator(self, enabled: bool):
|
||||
if enabled:
|
||||
self.helios_emission_indicator.setStyleSheet(
|
||||
"background-color: #ff2222; border-radius: 10px;"
|
||||
)
|
||||
else:
|
||||
self.helios_emission_indicator.setStyleSheet(
|
||||
"background-color: #444444; border-radius: 10px;"
|
||||
)
|
||||
|
||||
def _on_enable_toggle(self, checked: bool):
|
||||
self.helios_enable_btn.setText("Disable Laser" if checked else "Enable Laser")
|
||||
self._worker.queue_set_enable(checked)
|
||||
|
||||
def _on_enabled_updated(self, enabled: bool):
|
||||
self.helios_enable_btn.blockSignals(True)
|
||||
self.helios_enable_btn.setChecked(enabled)
|
||||
self.helios_enable_btn.setText("Disable Laser" if enabled else "Enable Laser")
|
||||
self.helios_enable_btn.blockSignals(False)
|
||||
self._set_emission_indicator(enabled)
|
||||
|
||||
def _on_set_current(self):
|
||||
self._worker.queue_set_current(self.helios_current_spin.value())
|
||||
|
||||
def _on_current_updated(self, current_ma: int):
|
||||
self.helios_current_spin.blockSignals(True)
|
||||
self.helios_current_spin.setValue(current_ma)
|
||||
self.helios_current_spin.blockSignals(False)
|
||||
|
||||
def _reset_temperatures(self):
|
||||
self.helios_temp_diode_label.setText("--- °C")
|
||||
self.helios_temp_pstage_label.setText("--- °C")
|
||||
self.helios_temp_qswitch_label.setText("--- °C")
|
||||
|
||||
def _on_status_registers(self, ler, lce, cce):
|
||||
self.helios_ler_label.setText(f"0x{ler:04X}" if ler is not None else "---")
|
||||
self.helios_lce_label.setText(f"0x{lce:04X}" if lce is not None else "---")
|
||||
self.helios_cce_label.setText(f"0x{cce:04X}" if cce is not None else "---")
|
||||
|
||||
def _update_controls(self, connected: bool):
|
||||
self.helios_enable_btn.setEnabled(connected)
|
||||
self.helios_current_spin.setEnabled(connected)
|
||||
self.helios_set_current_btn.setEnabled(connected)
|
||||
if not connected:
|
||||
self.helios_enable_btn.blockSignals(True)
|
||||
self.helios_enable_btn.setChecked(False)
|
||||
self.helios_enable_btn.setText("Enable Laser")
|
||||
self.helios_enable_btn.blockSignals(False)
|
||||
self._set_emission_indicator(False)
|
||||
self._reset_temperatures()
|
||||
self.helios_ler_label.setText("---")
|
||||
self.helios_lce_label.setText("---")
|
||||
self.helios_cce_label.setText("---")
|
||||
|
||||
|
||||
# ── Scan progress popup ───────────────────────────────────────────────────────
|
||||
|
||||
@@ -1013,8 +1346,14 @@ class MainWindow(QMainWindow):
|
||||
self._oscope_worker.moveToThread(self._oscope_thread)
|
||||
self._oscope_thread.started.connect(self._oscope_worker.run)
|
||||
|
||||
self._helios_thread = QThread(self)
|
||||
self._helios_worker = HeliosWorker()
|
||||
self._helios_worker.moveToThread(self._helios_thread)
|
||||
self._helios_thread.started.connect(self._helios_worker.run)
|
||||
|
||||
# ── Popup windows ─────────────────────────────────────────────────────
|
||||
self._camera_win = CameraWindow()
|
||||
self._helios_win = HeliosWindow(self._helios_worker)
|
||||
self._scan_progress = ScanProgressWindow()
|
||||
|
||||
self._scan_worker: ScanWorker | None = None
|
||||
@@ -1038,6 +1377,7 @@ class MainWindow(QMainWindow):
|
||||
self._t3r_thread.start()
|
||||
self._bbd_thread.start()
|
||||
self._oscope_thread.start()
|
||||
self._helios_thread.start()
|
||||
|
||||
# ── UI initialisation ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -1045,6 +1385,7 @@ class MainWindow(QMainWindow):
|
||||
self.t3r_comport_edit.setText(DEFAULT_T3R_PORT)
|
||||
self.bbd202_comport_edit.setText(DEFAULT_BBD_PORT)
|
||||
self.oscope_ip_edit.setText(DEFAULT_OSCOPE_IP)
|
||||
self._helios_win.helios_port_edit.setText(DEFAULT_HELIOS_PORT)
|
||||
self.t3r_jog_speed_edit.setText(str(GR_MOVE_SPEED_HZ))
|
||||
self.lineEdit_10.setText(str(BBD_DEFAULT_JOG_MM))
|
||||
|
||||
@@ -1131,8 +1472,17 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# Camera
|
||||
self.show_camera_toggle.toggled.connect(self._on_camera_toggle)
|
||||
self._camera_win.uc480_close_window_btn.clicked.connect(
|
||||
lambda: self.show_camera_toggle.setChecked(False)
|
||||
self._camera_win.closed.connect(
|
||||
lambda: self._set_toggle(self.show_camera_toggle, False, "Show Camera Window")
|
||||
)
|
||||
|
||||
# Helios
|
||||
self.show_helios_toggle.toggled.connect(self._on_helios_toggle)
|
||||
self._helios_win.closed.connect(
|
||||
lambda: self._set_toggle(self.show_helios_toggle, False, "Show Helios Panel")
|
||||
)
|
||||
self._helios_win.helios_close_btn.clicked.connect(
|
||||
lambda: self.show_helios_toggle.setChecked(False)
|
||||
)
|
||||
|
||||
# Scan
|
||||
@@ -1345,6 +1695,16 @@ class MainWindow(QMainWindow):
|
||||
self.show_camera_toggle.setText("Show Camera Window")
|
||||
self._camera_win.close()
|
||||
|
||||
# ── Helios toggle ─────────────────────────────────────────────────────────
|
||||
|
||||
def _on_helios_toggle(self, checked: bool):
|
||||
if checked:
|
||||
self.show_helios_toggle.setText("Hide Helios Panel")
|
||||
self._helios_win.show()
|
||||
else:
|
||||
self.show_helios_toggle.setText("Show Helios Panel")
|
||||
self._helios_win.close()
|
||||
|
||||
# ── Scan ──────────────────────────────────────────────────────────────────
|
||||
|
||||
def _on_browse_save_dir(self):
|
||||
@@ -1459,7 +1819,10 @@ class MainWindow(QMainWindow):
|
||||
self._bbd_worker.queue_disconnect()
|
||||
if self._oscope_worker.is_connected:
|
||||
self._oscope_worker.queue_disconnect()
|
||||
if self._helios_worker.is_connected:
|
||||
self._helios_worker.queue_disconnect()
|
||||
self._camera_win.close()
|
||||
self._helios_win.close()
|
||||
QTimer.singleShot(1500, QApplication.instance().quit)
|
||||
|
||||
# ── Helpers ───────────────────────────────────────────────────────────────
|
||||
@@ -1478,9 +1841,10 @@ class MainWindow(QMainWindow):
|
||||
def closeEvent(self, event):
|
||||
self._camera_win.close()
|
||||
self._scan_progress.close()
|
||||
for w in (self._t3r_worker, self._bbd_worker, self._oscope_worker):
|
||||
self._helios_win.close()
|
||||
for w in (self._t3r_worker, self._bbd_worker, self._oscope_worker, self._helios_worker):
|
||||
w.stop_worker()
|
||||
for t in (self._t3r_thread, self._bbd_thread, self._oscope_thread):
|
||||
for t in (self._t3r_thread, self._bbd_thread, self._oscope_thread, self._helios_thread):
|
||||
t.quit()
|
||||
t.wait(2000)
|
||||
super().closeEvent(event)
|
||||
|
||||
Reference in New Issue
Block a user