Files
ant-vision-inspector/main.py
2026-06-10 16:18:41 +09:00

157 lines
3.9 KiB
Python

# 엔트리포인트 — 스플래시 화면 표시 후 백그라운드 초기화, GUI 실행
import multiprocessing
import sys
from logger import setup_logging, teardown_logging
from PyQt5.QtWidgets import QApplication
from PyQt5.QtGui import QIcon
from utils.path_helper import get_path
from gui.main_window import MainWindow
from gui.splash_screen import SplashScreen, InitWorker
ICON_PATH = get_path("assets", "images", "ant_logo.png")
def _apply_windows_taskbar_icon(app_id: str = "ant.vision.inspection.1.0"):
if sys.platform != "win32":
return
try:
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(app_id)
except Exception as e:
print(f"[main] AppUserModelID 설정 실패: {e}")
def main():
# setup_logging() must be called inside main(), not at module level.
# On Windows, multiprocessing spawns subprocesses that re-import __main__,
# and module-level setup_logging() would corrupt the log file and replace
# builtins.print in every worker process.
setup_logging()
_apply_windows_taskbar_icon()
app = QApplication(sys.argv)
icon = QIcon(ICON_PATH)
app.setWindowIcon(icon)
app.setStyleSheet(_DARK_STYLE)
splash = SplashScreen()
splash.show()
QApplication.processEvents()
worker = InitWorker()
worker.progress.connect(splash.update_progress)
def on_finished(results):
window = MainWindow(
results["insight"],
results["basler"],
results["config"],
plc_client=results.get("plc"),
)
window.setWindowIcon(icon)
window.show()
splash.close()
def cleanup():
results["insight"].disconnect()
results["basler"].disconnect()
if results["db"].is_connected():
results["db"].disconnect()
plc = results.get("plc")
if plc and plc.is_connected():
plc.disconnect()
app.aboutToQuit.connect(cleanup)
worker.finished.connect(on_finished)
worker.start()
try:
ret = app.exec_()
finally:
teardown_logging()
sys.exit(ret)
_DARK_STYLE = """
QWidget {
background-color: #1a1a1a;
color: #ffffff;
font-size: 14px;
}
QGroupBox {
background-color: #222222;
border: 1px solid #444444;
border-radius: 6px;
margin-top: 14px;
padding: 10px 8px 8px 8px;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 4px;
color: #aaaaaa;
}
QPushButton {
background-color: #2e2e2e;
color: #ffffff;
border: 1px solid #555555;
border-radius: 4px;
min-height: 56px;
padding: 0 20px;
font-size: 14px;
}
QPushButton:hover { background-color: #3a3a3a; }
QPushButton:pressed { background-color: #1e1e1e; }
QPushButton:checked { background-color: #0055cc; border-color: #0077ff; }
QPushButton:disabled { color: #666666; }
QLineEdit, QSpinBox, QDoubleSpinBox {
background-color: #2a2a2a;
color: #ffffff;
border: 1px solid #555555;
border-radius: 4px;
padding: 6px 8px;
min-height: 38px;
}
QLabel { color: #ffffff; }
QListWidget {
background-color: #222222;
color: #ffffff;
border: 1px solid #444444;
outline: none;
}
QListWidget::item:selected { background-color: #0055cc; }
QProgressBar {
background-color: #2a2a2a;
border: 1px solid #555555;
border-radius: 4px;
text-align: center;
min-height: 22px;
}
QProgressBar::chunk { background-color: #0055cc; border-radius: 4px; }
QCheckBox { min-height: 38px; }
QCheckBox::indicator { width: 22px; height: 22px; }
QScrollBar:vertical {
background: #2a2a2a;
width: 10px;
border-radius: 5px;
}
QScrollBar::handle:vertical {
background: #555555;
border-radius: 5px;
min-height: 30px;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0; }
"""
if __name__ == "__main__":
multiprocessing.freeze_support()
main()