from PySide6.QtWidgets import QWidget from PySide6.QtCore import Qt, QRectF from PySide6.QtGui import QPainter, QColor, QPen, QFont, QBrush, QPainterPath class SpeedometerWidget(QWidget): def __init__(self, title="SPEED", unit="km/h", max_value=120, parent=None): super().__init__(parent) self.title = title self.unit = unit self.max_value = max_value self.current_value = 0.0 self.limit_value = 0.0 self.atc_code = 0 # ATC CODE 추가 self.setMinimumSize(120, 120) def set_value(self, value): try: self.current_value = float(value) except ValueError: self.current_value = 0.0 self.update() def set_limit(self, limit): try: self.limit_value = float(limit) except ValueError: self.limit_value = 0.0 self.update() def set_atc_code(self, code): """ATC CODE 설정""" try: self.atc_code = int(code) except (ValueError, TypeError): self.atc_code = 0 self.update() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) width = self.width() height = self.height() side = min(width, height) # 중앙 정렬 painter.translate(width / 2, height / 2) painter.scale(side / 200.0, side / 200.0) # 배경 (어두운 원) painter.setPen(Qt.NoPen) painter.setBrush(QColor(30, 30, 30)) painter.drawEllipse(-100, -100, 200, 200) # 눈금 그리기 (Start: 135도, Span: 270도) start_angle = 135 * 16 span_angle = -270 * 16 # 게이지 배경 (회색 아크) pen = QPen(QColor(60, 60, 60)) pen.setWidth(15) pen.setCapStyle(Qt.FlatCap) painter.setPen(pen) painter.drawArc(-80, -80, 160, 160, start_angle, span_angle) # 현재 속도 아크 (녹색/노란색/빨간색) if self.current_value > self.limit_value and self.limit_value > 0: color = QColor(255, 82, 82) # 초과 시 빨강 elif self.current_value > 0: color = QColor(0, 208, 132) # 평소 녹색 else: color = QColor(60, 60, 60) if self.current_value > 0: val_ratio = min(self.current_value / self.max_value, 1.0) val_span = int(span_angle * val_ratio) pen.setColor(color) painter.setPen(pen) painter.drawArc(-80, -80, 160, 160, start_angle, val_span) # 제한 속도 표시 (작은 마커) if self.limit_value > 0: limit_ratio = min(self.limit_value / self.max_value, 1.0) limit_angle = 135 + (270 * limit_ratio) painter.save() painter.rotate(limit_angle) painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 165, 0)) # 주황색 마커 painter.drawRect(-2, -95, 4, 10) # 눈금 위치에 마커 painter.restore() # ATC CODE 바늘 및 동그라미 표시 if self.atc_code > 0: # ATC CODE에 해당하는 각도 계산 (0~max_value 범위) atc_ratio = min(self.atc_code / self.max_value, 1.0) atc_angle = 135 + (270 * atc_ratio) painter.save() painter.rotate(atc_angle) # 빨간 바늘 (외부에서 내부로) pen = QPen(QColor(255, 50, 50)) pen.setWidth(3) painter.setPen(pen) painter.drawLine(0, -95, 0, -70) # 외부(-95)에서 내부(-70)로 # 바늘 외부에 동그라미 painter.setPen(Qt.NoPen) painter.setBrush(QColor(255, 50, 50)) painter.drawEllipse(-8, -110, 16, 16) # 바늘 외부에 원 # 동그라미 안에 ATC CODE 텍스트 painter.setPen(QColor(255, 255, 255)) font = QFont("Arial", 8, QFont.Bold) painter.setFont(font) painter.drawText(QRectF(-8, -110, 16, 16), Qt.AlignCenter, str(self.atc_code)) painter.restore() # 텍스트 표시 painter.setPen(QColor(255, 255, 255)) # 현재 값 (큰 글씨) font = QFont("Arial", 28, QFont.Bold) painter.setFont(font) painter.drawText(QRectF(-100, -20, 200, 40), Qt.AlignCenter, f"{self.current_value:.1f}") # 단위 (작은 글씨) font.setPointSize(10) painter.setFont(font) painter.drawText(QRectF(-100, 20, 200, 20), Qt.AlignCenter, self.unit) # 타이틀 (상단) font.setPointSize(12) painter.setFont(font) painter.setPen(QColor(180, 180, 180)) painter.drawText(QRectF(-100, -70, 200, 20), Qt.AlignCenter, self.title)