AI_MMI_Analyser/app/ui/components/speedometer.py

139 lines
4.8 KiB
Python

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)