import json import os from PyQt5.QtWidgets import QWidget, QLabel, QProgressBar, QVBoxLayout, QApplication from PyQt5.QtCore import Qt, QThread, pyqtSignal from PyQt5.QtGui import QPainter, QPainterPath, QColor class SplashScreen(QWidget): def __init__(self): super().__init__() self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground) self.setFixedSize(500, 300) screen = QApplication.primaryScreen().geometry() self.move( (screen.width() - self.width()) // 2, (screen.height() - self.height()) // 2, ) self._build_ui() def _build_ui(self): layout = QVBoxLayout(self) layout.setContentsMargins(40, 40, 40, 30) layout.setSpacing(0) title = QLabel("리플렉터 검사 시스템") title.setAlignment(Qt.AlignCenter) title.setStyleSheet( "color:#ffffff; font-size:22px; font-weight:bold; background:transparent;" ) subtitle = QLabel("Reflector Inspection System") subtitle.setAlignment(Qt.AlignCenter) subtitle.setStyleSheet("color:#555555; font-size:12px; background:transparent;") layout.addStretch(2) layout.addWidget(title) layout.addSpacing(6) layout.addWidget(subtitle) layout.addStretch(3) self.status_label = QLabel("초기화 중...") self.status_label.setAlignment(Qt.AlignCenter) self.status_label.setStyleSheet( "color:#888888; font-size:13px; background:transparent;" ) layout.addWidget(self.status_label) layout.addSpacing(10) self.progress_bar = QProgressBar() self.progress_bar.setRange(0, 100) self.progress_bar.setValue(0) self.progress_bar.setFixedHeight(6) self.progress_bar.setTextVisible(False) self.progress_bar.setStyleSheet(""" QProgressBar { background: #2a2a2a; border: none; border-radius: 3px; } QProgressBar::chunk { background: #1D9E75; border-radius: 3px; } """) layout.addWidget(self.progress_bar) layout.addStretch(1) version = QLabel("v1.0.0") version.setAlignment(Qt.AlignCenter) version.setStyleSheet("color:#333333; font-size:11px; background:transparent;") layout.addWidget(version) def update_progress(self, value: int, message: str): self.progress_bar.setValue(value) self.status_label.setText(message) QApplication.processEvents() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) path = QPainterPath() path.addRoundedRect(0.0, 0.0, float(self.width()), float(self.height()), 12.0, 12.0) painter.fillPath(path, QColor("#0d0d0d")) class InitWorker(QThread): progress = pyqtSignal(int, str) # (진행률, 메시지) finished = pyqtSignal(object) # 초기화 결과 dict def run(self): from utils.path_helper import get_path from camera.insight import InSightCamera from camera.basler import BaslerCamera from ai.detector import Detector from db.sql_client import SQLClient results = {} # ── 1단계: 설정 로드 ──────────────────────────────────────────── # self.progress.emit(10, "설정 불러오는 중...") try: with open(get_path("config.json"), encoding="utf-8") as f: config = json.load(f) except Exception as e: print(f"[InitWorker] 설정 로드 실패: {e}") config = {} results["config"] = config # ── 2단계: 코그넥스 카메라 ────────────────────────────────────── # self.progress.emit(25, "코그넥스 카메라 연결 중...") insight = InSightCamera() try: cognex_cfg = config.get("cognex", {}) ip = cognex_cfg.get("ip", "") port = cognex_cfg.get("port", 23) if ip: insight.connect(ip, port) except Exception as e: print(f"[InitWorker] 코그넥스 연결 실패: {e}") results["insight"] = insight # ── 3단계: Basler 카메라 ──────────────────────────────────────── # self.progress.emit(45, "Basler 카메라 연결 중...") basler = BaslerCamera() try: basler.connect() except Exception as e: print(f"[InitWorker] Basler 연결 실패: {e}") results["basler"] = basler # ── 4단계: AI 모델 로드 ───────────────────────────────────────── # self.progress.emit(65, "AI 모델 로드 중...") detector = Detector() try: from paths import resolve_path model_path = config.get("ai", {}).get("model_path", "") if model_path: abs_path = resolve_path(model_path) if abs_path and os.path.exists(abs_path): detector.load_model(abs_path) except Exception as e: print(f"[InitWorker] AI 모델 로드 실패: {e}") results["detector"] = detector # ── 5단계: DB 연결 ────────────────────────────────────────────── # self.progress.emit(80, "DB 연결 중...") db_client = SQLClient() try: db_cfg = config.get("db", {}) if db_cfg.get("server"): db_client.connect( db_cfg["server"], db_cfg["database"], db_cfg["username"], db_cfg["password"], ) except Exception as e: print(f"[InitWorker] DB 연결 실패: {e}") results["db"] = db_client # ── 6단계: PLC 연결 ───────────────────────────────────────────── # self.progress.emit(92, "PLC 연결 중...") plc_client = None try: from plc.plc_client import PLCClient plc_cfg = config.get("plc", {}) ip = plc_cfg.get("ip", "").strip() port = plc_cfg.get("port", 5010) if ip: client = PLCClient() if client.connect(ip, port): plc_client = client except Exception as e: print(f"[InitWorker] PLC 연결 실패: {e}") results["plc"] = plc_client # ── 완료 ──────────────────────────────────────────────────────── # self.progress.emit(100, "시작 중...") self.finished.emit(results)