基本界面达成
This commit is contained in:
@@ -2,9 +2,12 @@ import os
|
||||
import json
|
||||
import re
|
||||
from PyQt6.QtWidgets import (QWidget, QHBoxLayout, QVBoxLayout,
|
||||
QPushButton, QLabel, QFrame, QGraphicsView, QGraphicsScene, QGraphicsPathItem)
|
||||
from PyQt6.QtCore import Qt, QTimer, QThread, pyqtSignal, QUrl, QObject, pyqtProperty, QRectF
|
||||
from PyQt6.QtGui import QColor, QPen, QPainter, QPainterPath
|
||||
QPushButton, QLabel, QFrame, QGraphicsView,
|
||||
QGraphicsScene, QGraphicsPathItem, QProgressBar)
|
||||
from PyQt6.QtCore import Qt, QTimer, QThread, pyqtSignal, QUrl, QObject, pyqtProperty, QRectF, QSize
|
||||
from PyQt6.QtGui import QColor, QPen, QPainter, QPainterPath, QFont, QLinearGradient, QBrush
|
||||
from utils.config_parse import ConfigParse
|
||||
|
||||
|
||||
def get_gcode_dir():
|
||||
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config.json")
|
||||
@@ -17,167 +20,390 @@ def get_gcode_dir():
|
||||
|
||||
GCODE_DIR = get_gcode_dir()
|
||||
|
||||
class GCode2DPreviewWidget(QGraphicsView):
|
||||
def __init__(self, parent=None):
|
||||
# ── 状态主题色 ──────────────────────────────────────────
|
||||
STATUS_COLORS = {
|
||||
"Operational": "#4CAF50",
|
||||
"Printing": "#2196F3",
|
||||
"Paused": "#FF9800",
|
||||
"Error": "#F44336",
|
||||
"Offline": "#9E9E9E",
|
||||
"Cancelling": "#FF5722",
|
||||
"Finishing": "#8BC34A",
|
||||
}
|
||||
STATUS_LABELS = {
|
||||
"Operational": "就绪",
|
||||
"Printing": "打印中",
|
||||
"Paused": "已暂停",
|
||||
"Error": "错误",
|
||||
"Offline": "离线",
|
||||
"Cancelling": "取消中",
|
||||
"Finishing": "整理中",
|
||||
}
|
||||
|
||||
|
||||
class CardFrame(QFrame):
|
||||
"""统一的信息卡片样式"""
|
||||
|
||||
def __init__(self, title="", parent=None):
|
||||
super().__init__(parent)
|
||||
self.scene = QGraphicsScene(self)
|
||||
self.setScene(self.scene)
|
||||
self.setStyleSheet("background-color: #111111; border-radius: 5px; border: 1px solid #666;")
|
||||
self.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
# 翻转Y轴让(0,0)位于左下角,适配物理坐标系
|
||||
self.scale(1, -1)
|
||||
self.setStyleSheet("""
|
||||
CardFrame {
|
||||
background-color: #3a3a3a;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 8px;
|
||||
}
|
||||
""")
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(12, 10, 12, 10)
|
||||
layout.setSpacing(4)
|
||||
|
||||
def draw_paths(self, lines_data):
|
||||
self.scene.clear()
|
||||
bounding_rect = QRectF()
|
||||
|
||||
for color_str, data in lines_data.items():
|
||||
points = data.get("points", [])
|
||||
line_width = data.get("line_width", 2)
|
||||
|
||||
if not points:
|
||||
continue
|
||||
|
||||
path = QPainterPath()
|
||||
|
||||
# 判断是一组连续点的坐标(单线条)[[x1,y1], [x2,y2]]
|
||||
# 还是包含多根独立线条 [[[x1,y1], [x2,y2]], [[x3,y3], [x4,y4]]]
|
||||
if isinstance(points[0][0], (int, float)):
|
||||
path.moveTo(float(points[0][0]), float(points[0][1]))
|
||||
for pt in points[1:]:
|
||||
path.lineTo(float(pt[0]), float(pt[1]))
|
||||
else:
|
||||
for line_pts in points:
|
||||
if not line_pts:
|
||||
continue
|
||||
path.moveTo(float(line_pts[0][0]), float(line_pts[0][1]))
|
||||
for pt in line_pts[1:]:
|
||||
path.lineTo(float(pt[0]), float(pt[1]))
|
||||
|
||||
path_item = QGraphicsPathItem(path)
|
||||
|
||||
# 安全获取颜色
|
||||
pen_color = QColor(color_str) if QColor.isValidColor(color_str) else QColor("white")
|
||||
|
||||
pen = QPen(pen_color)
|
||||
pen.setWidth(int(line_width))
|
||||
# 保持 Cosmetic,以确保视图缩放时线条粗细在屏幕上看起来一致
|
||||
pen.setCosmetic(True)
|
||||
path_item.setPen(pen)
|
||||
|
||||
self.scene.addItem(path_item)
|
||||
bounding_rect = bounding_rect.united(path.boundingRect())
|
||||
|
||||
# 设置场景范围以便居中缩放
|
||||
if bounding_rect.width() < 1 or bounding_rect.height() < 1:
|
||||
bounding_rect = QRectF(0, 0, 220, 220)
|
||||
|
||||
bounding_rect.adjust(-10, -10, 10, 10)
|
||||
self.scene.setSceneRect(bounding_rect)
|
||||
self.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||
if title:
|
||||
title_lbl = QLabel(title)
|
||||
title_lbl.setStyleSheet("color: #aaaaaa; font-size: 13px; font-weight: 500; border: none;")
|
||||
layout.addWidget(title_lbl)
|
||||
|
||||
self.content_layout = layout
|
||||
|
||||
def add_row(self, label, value_widget):
|
||||
row = QHBoxLayout()
|
||||
row.setSpacing(8)
|
||||
lbl = QLabel(label)
|
||||
lbl.setStyleSheet("color: #cccccc; font-size: 15px; border: none;")
|
||||
lbl.setFixedWidth(70)
|
||||
row.addWidget(lbl)
|
||||
row.addWidget(value_widget, 1)
|
||||
self.content_layout.addLayout(row)
|
||||
|
||||
|
||||
class TempGauge(QWidget):
|
||||
"""温度计指示器"""
|
||||
|
||||
def __init__(self, label="Tool", parent=None):
|
||||
super().__init__(parent)
|
||||
self.setFixedSize(100, 80)
|
||||
self._label = label
|
||||
self._actual = 0.0
|
||||
self._target = 0.0
|
||||
|
||||
def set_value(self, actual, target):
|
||||
self._actual = actual
|
||||
self._target = target
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, event):
|
||||
p = QPainter(self)
|
||||
p.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
w, h = self.width(), self.height()
|
||||
|
||||
# 背景条
|
||||
bar_x, bar_w = 16, 20
|
||||
bar_y, bar_h = 10, 56
|
||||
p.setPen(QPen(QColor("#555555"), 1))
|
||||
p.setBrush(QBrush(QColor("#2a2a2a")))
|
||||
p.drawRoundedRect(bar_x, bar_y, bar_w, bar_h, 4, 4)
|
||||
|
||||
# 填充柱(按温度比例,最高 300°C)
|
||||
ratio = min(max(self._actual / 300, 0), 1)
|
||||
fill_h = int((bar_h - 4) * ratio)
|
||||
if fill_h > 0:
|
||||
grad = QLinearGradient(0, bar_y + bar_h, 0, bar_y)
|
||||
grad.setColorAt(0, QColor("#f57c00"))
|
||||
grad.setColorAt(1, QColor("#e53935") if self._actual > 200 else QColor("#ffb74d"))
|
||||
p.setBrush(QBrush(grad))
|
||||
p.setPen(Qt.PenStyle.NoPen)
|
||||
p.drawRoundedRect(bar_x + 2, bar_y + bar_h - 2 - fill_h, bar_w - 4, fill_h, 3, 3)
|
||||
|
||||
# 目标值标记线
|
||||
if self._target > 0:
|
||||
tgt_y = bar_y + bar_h - int((bar_h - 4) * min(self._target / 300, 1))
|
||||
p.setPen(QPen(QColor("#ffffff"), 2))
|
||||
p.drawLine(bar_x - 2, tgt_y, bar_x + bar_w + 2, tgt_y)
|
||||
|
||||
# 文字
|
||||
font = QFont("sans-serif", 11, QFont.Weight.Bold)
|
||||
p.setFont(font)
|
||||
p.setPen(QPen(QColor("#e0e0e0")))
|
||||
p.drawText(44, 16, w - 44, 24, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
|
||||
f"{self._actual:.0f}°")
|
||||
if self._target > 0:
|
||||
font2 = QFont("sans-serif", 10)
|
||||
p.setFont(font2)
|
||||
p.setPen(QPen(QColor("#888888")))
|
||||
p.drawText(44, 34, w - 44, 20, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
|
||||
f"→ {self._target:.0f}°")
|
||||
|
||||
font3 = QFont("sans-serif", 10, QFont.Weight.Bold)
|
||||
p.setFont(font3)
|
||||
p.setPen(QPen(QColor("#aaaaaa")))
|
||||
p.drawText(0, h - 20, w, 20, Qt.AlignmentFlag.AlignCenter, self._label)
|
||||
|
||||
|
||||
# ── GCode 2D 预览(暂注释,待开发)─────────────────────
|
||||
# class GCode2DPreviewWidget(QGraphicsView):
|
||||
# def __init__(self, parent=None):
|
||||
# super().__init__(parent)
|
||||
# self.scene = QGraphicsScene(self)
|
||||
# self.setScene(self.scene)
|
||||
# self.setStyleSheet("background-color: #111111; border-radius: 5px; border: 1px solid #666;")
|
||||
# self.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
# self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
# self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
# self.scale(1, -1)
|
||||
#
|
||||
# def draw_paths(self, lines_data):
|
||||
# self.scene.clear()
|
||||
# bounding_rect = QRectF()
|
||||
# for color_str, data in lines_data.items():
|
||||
# points = data.get("points", [])
|
||||
# line_width = data.get("line_width", 2)
|
||||
# if not points:
|
||||
# continue
|
||||
# path = QPainterPath()
|
||||
# if isinstance(points[0][0], (int, float)):
|
||||
# path.moveTo(float(points[0][0]), float(points[0][1]))
|
||||
# for pt in points[1:]:
|
||||
# path.lineTo(float(pt[0]), float(pt[1]))
|
||||
# else:
|
||||
# for line_pts in points:
|
||||
# if not line_pts:
|
||||
# continue
|
||||
# path.moveTo(float(line_pts[0][0]), float(line_pts[0][1]))
|
||||
# for pt in line_pts[1:]:
|
||||
# path.lineTo(float(pt[0]), float(pt[1]))
|
||||
# path_item = QGraphicsPathItem(path)
|
||||
# pen_color = QColor(color_str) if QColor.isValidColor(color_str) else QColor("white")
|
||||
# pen = QPen(pen_color)
|
||||
# pen.setWidth(int(line_width))
|
||||
# pen.setCosmetic(True)
|
||||
# path_item.setPen(pen)
|
||||
# self.scene.addItem(path_item)
|
||||
# bounding_rect = bounding_rect.united(path.boundingRect())
|
||||
# if bounding_rect.width() < 1 or bounding_rect.height() < 1:
|
||||
# bounding_rect = QRectF(0, 0, 220, 220)
|
||||
# bounding_rect.adjust(-10, -10, 10, 10)
|
||||
# self.scene.setSceneRect(bounding_rect)
|
||||
# self.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||
|
||||
|
||||
# ── 状态页面 ────────────────────────────────────────────
|
||||
class StatusPage(QWidget):
|
||||
def __init__(self, api_client, parent=None):
|
||||
super().__init__(parent)
|
||||
self.api_client = api_client
|
||||
|
||||
self.file_name = "None"
|
||||
self.progress = 0
|
||||
self.progress = 0.0
|
||||
self.display_name = "None"
|
||||
self.state = "Unknown"
|
||||
self.print_time = 0
|
||||
self.print_time_left = 0
|
||||
self.tool_temp_actual = 0.0
|
||||
self.tool_temp_target = 0.0
|
||||
self.bed_temp_actual = 0.0
|
||||
self.bed_temp_target = 0.0
|
||||
|
||||
self.config_parser = ConfigParse()
|
||||
self.config_parser.config_changed.connect(self._on_config_changed)
|
||||
self.gcode_dir = self.config_parser.gcode_dir
|
||||
|
||||
self.init_ui()
|
||||
|
||||
self.timer = QTimer(self)
|
||||
self.timer.timeout.connect(self.update_status)
|
||||
self.timer.start(1000)
|
||||
self.update_status()
|
||||
|
||||
def _on_config_changed(self, config_instance):
|
||||
self.gcode_dir = self.config_parser.gcode_dir
|
||||
|
||||
def fresh_status_valve(self):
|
||||
data = self.api_client.get_status()
|
||||
# print("Status Data:", data)
|
||||
if data:
|
||||
status = data.get("status", {})
|
||||
job = data.get("job", {})
|
||||
self.file_name = job.get("job", {}).get("file", {}).get("name", "None")
|
||||
self.progress = job.get("progress", {}).get("completion", 0)
|
||||
self.progress = job.get("progress", {}).get("completion", 0) or 0
|
||||
self.display_name = job.get("job", {}).get("file", {}).get("display_name", "None")
|
||||
self.state = status.get("state", {}).get("text", "Offline")
|
||||
self.print_time = job.get("progress", {}).get("printTime", 0)
|
||||
self.print_time_left = job.get("progress", {}).get("printTimeLeft", 0)
|
||||
self.print_time = job.get("progress", {}).get("printTime", 0) or 0
|
||||
self.print_time_left = job.get("progress", {}).get("printTimeLeft", 0) or 0
|
||||
temp = status.get("temperature", {})
|
||||
self.tool_temp_actual = (temp.get("tool0", {}) or {}).get("actual", 0) or 0
|
||||
self.tool_temp_target = (temp.get("tool0", {}) or {}).get("target", 0) or 0
|
||||
self.bed_temp_actual = (temp.get("bed", {}) or {}).get("actual", 0) or 0
|
||||
self.bed_temp_target = (temp.get("bed", {}) or {}).get("target", 0) or 0
|
||||
|
||||
# print(f"Updated Status: state={self.state}, file_name={self.file_name}, progress={self.progress:.1f}%, display_name={self.display_name}")
|
||||
def format_time(self, seconds):
|
||||
if seconds is None:
|
||||
@staticmethod
|
||||
def format_time(seconds):
|
||||
if seconds is None or seconds == 0:
|
||||
return "N/A"
|
||||
m, s = divmod(seconds, 60)
|
||||
m, s = divmod(int(seconds), 60)
|
||||
h, m = divmod(m, 60)
|
||||
if h > 0:
|
||||
return f"{int(h)}h {int(m)}m {int(s)}s"
|
||||
return f"{h}h {m:02d}m {s:02d}s"
|
||||
elif m > 0:
|
||||
return f"{int(m)}m {int(s)}s"
|
||||
return f"{m}m {s:02d}s"
|
||||
else:
|
||||
return f"{int(s)}s"
|
||||
return f"{s}s"
|
||||
|
||||
def _make_card(self, title=""):
|
||||
card = CardFrame(title)
|
||||
return card
|
||||
|
||||
def _truncate(self, text, max_len=22):
|
||||
return text if len(text) <= max_len else text[:max_len - 2] + "…"
|
||||
|
||||
def init_ui(self):
|
||||
self.fresh_status_valve()
|
||||
main_layout = QHBoxLayout(self)
|
||||
|
||||
self.left_frame = QFrame()
|
||||
self.left_frame.setStyleSheet("background-color: #444444; border-radius: 10px; color: white;")
|
||||
left_layout = QVBoxLayout(self.left_frame)
|
||||
|
||||
self.lbl_status = QLabel(f"Status: {self.state}")
|
||||
left_layout.addWidget(self.lbl_status)
|
||||
self.lbl_job = QLabel(f"File: {self.display_name}")
|
||||
left_layout.addWidget(self.lbl_job)
|
||||
self.lbl_progress = QLabel(f"Progress: {self.progress if self.progress else 0:.1f}%")
|
||||
left_layout.addWidget(self.lbl_progress)
|
||||
self.lbl_print_time = QLabel(f"Print Time: {self.format_time(self.print_time)}")
|
||||
left_layout.addWidget(self.lbl_print_time)
|
||||
self.lbl_print_time_left = QLabel(f"Print Time Left: {self.format_time(self.print_time_left)}")
|
||||
left_layout.addWidget(self.lbl_print_time_left)
|
||||
left_layout.addStretch()
|
||||
|
||||
#TODO: 3D Gcode View in right frame, use QML and QtQuick3D to render the Gcode vertices, pass the progress to QML to show the current layer
|
||||
# Due to the complexity of parsing Gcode and rendering it in 3D, this part will be implemented in a separate thread to avoid blocking the UI, and the vertices will be passed to QML for rendering. The progress will also be passed to QML to show the current layer being printed.
|
||||
# Load QtQuick3D View
|
||||
# self.right_frame = QFrame()
|
||||
# right_layout = QVBoxLayout(self.right_frame)
|
||||
# self.view = QQuickView()
|
||||
# self.view.setResizeMode(QQuickView.ResizeMode.SizeRootObjectToView)
|
||||
# qml_file = os.path.join(os.path.dirname(__file__), "gcode_view2.qml")
|
||||
|
||||
# self.view.setSource(QUrl.fromLocalFile(qml_file))
|
||||
# gcode_data = self.load_gcode_vertices(os.path.join(GCODE_DIR, self.file_name))
|
||||
# self.view.rootContext().setContextProperty("gcodeData", gcode_data)
|
||||
# container = QWidget.createWindowContainer(self.view, self)
|
||||
# right_layout.addWidget(container)
|
||||
main_layout.setContentsMargins(8, 8, 8, 8)
|
||||
main_layout.setSpacing(8)
|
||||
|
||||
self.right_frame = QFrame()
|
||||
self.right_frame.setStyleSheet("background-color: #444444; border-radius: 10px;")
|
||||
right_layout = QVBoxLayout(self.right_frame)
|
||||
|
||||
self.gcode_view = GCode2DPreviewWidget()
|
||||
right_layout.addWidget(self.gcode_view)
|
||||
|
||||
main_layout.addWidget(self.left_frame, 1)
|
||||
main_layout.addWidget(self.right_frame, 2)
|
||||
# ── 左侧信息面板 ──────────────────────────────────
|
||||
left_frame = QFrame()
|
||||
left_frame.setStyleSheet("background-color: #333333; border-radius: 10px;")
|
||||
left_layout = QVBoxLayout(left_frame)
|
||||
left_layout.setContentsMargins(10, 10, 10, 10)
|
||||
left_layout.setSpacing(6)
|
||||
|
||||
# — 状态徽章 —
|
||||
self._status_badge = QLabel()
|
||||
self._status_badge.setFixedHeight(40)
|
||||
self._status_badge.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
font_badge = QFont("sans-serif", 18, QFont.Weight.Bold)
|
||||
self._status_badge.setFont(font_badge)
|
||||
left_layout.addWidget(self._status_badge)
|
||||
|
||||
# — 文件信息卡片 —
|
||||
self._file_card = CardFrame("当前文件")
|
||||
self._file_name_lbl = QLabel("--")
|
||||
self._file_name_lbl.setStyleSheet("color: #ffffff; font-size: 16px; font-weight: 600; border: none;")
|
||||
self._file_name_lbl.setWordWrap(True)
|
||||
self._file_card.content_layout.addWidget(self._file_name_lbl)
|
||||
left_layout.addWidget(self._file_card)
|
||||
|
||||
# — 进度卡片 —
|
||||
self._progress_card = CardFrame("打印进度")
|
||||
# 进度条
|
||||
self._progress_bar = QProgressBar()
|
||||
self._progress_bar.setTextVisible(True)
|
||||
self._progress_bar.setFixedHeight(28)
|
||||
self._progress_bar.setStyleSheet("""
|
||||
QProgressBar {
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #555;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
""")
|
||||
self._progress_card.content_layout.addWidget(self._progress_bar)
|
||||
# 时间行
|
||||
time_row = QHBoxLayout()
|
||||
time_row.setSpacing(10)
|
||||
self._time_elapsed_lbl = QLabel("已用: --")
|
||||
self._time_elapsed_lbl.setStyleSheet("color: #bbbbbb; font-size: 14px; border: none;")
|
||||
self._time_left_lbl = QLabel("剩余: --")
|
||||
self._time_left_lbl.setStyleSheet("color: #bbbbbb; font-size: 14px; border: none;")
|
||||
time_row.addWidget(self._time_elapsed_lbl)
|
||||
time_row.addStretch()
|
||||
time_row.addWidget(self._time_left_lbl)
|
||||
self._progress_card.content_layout.addLayout(time_row)
|
||||
left_layout.addWidget(self._progress_card)
|
||||
|
||||
# — 温度卡片 —
|
||||
self._temp_card = CardFrame("温度")
|
||||
temp_row = QHBoxLayout()
|
||||
temp_row.setSpacing(8)
|
||||
self._tool_gauge = TempGauge("喷头")
|
||||
self._bed_gauge = TempGauge("热床")
|
||||
temp_row.addWidget(self._tool_gauge)
|
||||
temp_row.addWidget(self._bed_gauge)
|
||||
temp_row.addStretch()
|
||||
self._temp_card.content_layout.addLayout(temp_row)
|
||||
left_layout.addWidget(self._temp_card)
|
||||
|
||||
left_layout.addStretch()
|
||||
|
||||
# ── 右侧预留区域 ─────────────────────────────
|
||||
right_frame = QFrame()
|
||||
right_frame.setStyleSheet("background-color: #3a3a3a; border-radius: 10px;")
|
||||
right_layout = QVBoxLayout(right_frame)
|
||||
right_layout.setContentsMargins(6, 6, 6, 6)
|
||||
|
||||
placeholder = QLabel("GCode 预览\n⚙ 待开发")
|
||||
placeholder.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
placeholder.setStyleSheet("color: #666666; font-size: 24px; font-weight: 600; border: none;")
|
||||
right_layout.addWidget(placeholder)
|
||||
|
||||
main_layout.addWidget(left_frame, 2)
|
||||
main_layout.addWidget(right_frame, 3)
|
||||
|
||||
def update_status(self):
|
||||
self.fresh_status_valve()
|
||||
self.lbl_status.setText(f"Status: {self.state}")
|
||||
|
||||
self.lbl_job.setText(f"File: {self.display_name}")
|
||||
|
||||
self.lbl_progress.setText(f"Progress: {self.progress if self.progress else 0:.1f}%")
|
||||
|
||||
# Pass progress to QML
|
||||
# root_obj = self.view.rootObject()
|
||||
# if root_obj:
|
||||
# root_obj.setProperty("progress", prog if prog else 0)
|
||||
# 状态徽章
|
||||
status_key = self.state.split()[0] if self.state else "Offline"
|
||||
color = STATUS_COLORS.get(status_key, "#9E9E9E")
|
||||
label = STATUS_LABELS.get(status_key, self.state)
|
||||
self._status_badge.setText(f"● {label}")
|
||||
self._status_badge.setStyleSheet(
|
||||
f"background-color: #2a2a2a; color: {color}; "
|
||||
f"border: 2px solid {color}; border-radius: 8px; "
|
||||
f"font-size: 18px; font-weight: bold; padding: 4px;"
|
||||
)
|
||||
|
||||
# 文件
|
||||
self._file_name_lbl.setText(self._truncate(self.display_name, 28))
|
||||
|
||||
# 进度
|
||||
prog = min(max(self.progress, 0), 100)
|
||||
self._progress_bar.setValue(int(prog))
|
||||
self._progress_bar.setFormat(f"{prog:.1f}%")
|
||||
self._time_elapsed_lbl.setText(f"已用: {self.format_time(self.print_time)}")
|
||||
self._time_left_lbl.setText(f"剩余: {self.format_time(self.print_time_left)}")
|
||||
# 打印中时进度条变蓝
|
||||
if self.state.startswith("Printing"):
|
||||
self._progress_bar.setStyleSheet("""
|
||||
QProgressBar {
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #555;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
background-color: #2196F3;
|
||||
border-radius: 5px;
|
||||
}
|
||||
""")
|
||||
else:
|
||||
self._progress_bar.setStyleSheet("""
|
||||
QProgressBar {
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #555;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
background-color: #4CAF50;
|
||||
border-radius: 5px;
|
||||
}
|
||||
""")
|
||||
|
||||
# 温度
|
||||
self._tool_gauge.set_value(self.tool_temp_actual, self.tool_temp_target)
|
||||
self._bed_gauge.set_value(self.bed_temp_actual, self.bed_temp_target)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user