From b893c30eb30fb7e56ffdf2883a22b4714383c2e2 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Tue, 17 Jun 2025 21:33:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84MRUI=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MRobot.py | 180 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 155 insertions(+), 25 deletions(-) diff --git a/MRobot.py b/MRobot.py index 0347029..118275b 100644 --- a/MRobot.py +++ b/MRobot.py @@ -7,12 +7,22 @@ from PyQt5.QtGui import QTextCursor from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtWidgets import QHBoxLayout, QComboBox, QPushButton, QTextEdit, QLineEdit, QLabel from PyQt5.QtWidgets import QGroupBox, QGridLayout, QSizePolicy - +from qfluentwidgets import Theme, setTheme from qfluentwidgets import ( NavigationItemPosition, Theme, FluentWindow, NavigationAvatarWidget, PushButton, FluentIcon ) from qfluentwidgets import FluentIcon as FIF +from qfluentwidgets import Theme, setTheme, FluentIcon, SwitchButton +from qfluentwidgets import BodyLabel +from qfluentwidgets import BodyLabel, TextEdit, LineEdit, ComboBox, PushButton, SwitchButton +from qfluentwidgets import BodyLabel, SubtitleLabel, StrongBodyLabel, HorizontalSeparator, InfoBar +from qfluentwidgets import MessageDialog +from qfluentwidgets import Dialog, StrongBodyLabel, BodyLabel, SubtitleLabel, AvatarWidget +from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget +from qfluentwidgets import Dialog +from qfluentwidgets import StrongBodyLabel, SubtitleLabel, BodyLabel, PushButton, AvatarWidget, HorizontalSeparator +from qfluentwidgets import ImageLabel # ===================== 页面基类 ===================== class BaseInterface(QWidget): @@ -20,13 +30,67 @@ class BaseInterface(QWidget): super().__init__(parent=parent) # ===================== 首页界面 ===================== +# ...existing code... + +# ...existing code... + class HomeInterface(BaseInterface): def __init__(self, parent=None): super().__init__(parent=parent) self.setObjectName("homeInterface") layout = QVBoxLayout() + layout.setContentsMargins(60, 60, 60, 60) + layout.setSpacing(32) self.setLayout(layout) + # 顶部logo和欢迎区 + top_layout = QHBoxLayout() + logo = ImageLabel('img/MRobot.png') + logo.setFixedSize(260, 80) + top_layout.addWidget(logo, alignment=Qt.AlignmentFlag.AlignTop) + title_layout = QVBoxLayout() + title_layout.addWidget(StrongBodyLabel("欢迎使用 MRobot Toolbox")) + title_layout.addWidget(SubtitleLabel("让你的机器人开发更高效、更智能")) + top_layout.addLayout(title_layout) + top_layout.addStretch() + layout.addLayout(top_layout) + + layout.addWidget(HorizontalSeparator()) + + # 项目简介 + layout.addWidget(BodyLabel( + "MRobot Toolbox 是一款集成化的机器人开发辅助工具," + "支持代码生成、串口终端、主题切换等多种实用功能。\n" + "点击左侧导航栏可快速切换各功能页面。" + )) + + # 开发者与项目目标 + layout.addWidget(HorizontalSeparator()) + layout.addWidget(SubtitleLabel("开发者与项目目标")) + layout.addWidget(BodyLabel("开发团队:QUT 青岛理工大学 MOVE 战队")) + layout.addWidget(BodyLabel("项目目标:为所有 rmer 和 rcer 提供现代化、简单、高效的机器人开发方式," + "让机器人开发变得更轻松、更智能。")) + layout.addWidget(BodyLabel("适用于 RM、RC、各类嵌入式机器人项目。")) + + # # 开源与版本信息 + # layout.addWidget(HorizontalSeparator()) + # layout.addWidget(SubtitleLabel("项目信息")) + # layout.addWidget(BodyLabel("开源地址: https://github.com/QUT-MOVE/MRobot-Toolbox")) + # layout.addWidget(BodyLabel("当前版本: v1.0.0")) + # layout.addWidget(BodyLabel("反馈邮箱: move@qut.edu.cn")) + + # # 致谢 + # layout.addWidget(HorizontalSeparator()) + # layout.addWidget(SubtitleLabel("致谢")) + # layout.addWidget(BodyLabel("感谢所有开源社区贡献者,特别感谢 RM/RC 机器人开发者的持续支持。")) + + layout.addStretch() + +# ...existing code... + +# ...existing code... + + # ===================== 代码生成页面 ===================== class DataInterface(BaseInterface): def __init__(self, parent=None): @@ -65,15 +129,15 @@ class SerialTerminalInterface(BaseInterface): # 串口选择和连接 hbox = QHBoxLayout() - self.port_combo = QComboBox() + self.port_combo = ComboBox() # 替换QComboBox为ComboBox self.refresh_ports() - self.baud_combo = QComboBox() + self.baud_combo = ComboBox() # 替换QComboBox为ComboBox self.baud_combo.addItems(['9600', '115200', '57600', '38400', '19200', '4800']) - self.connect_btn = QPushButton("连接") + self.connect_btn = PushButton("连接") # 替换QPushButton为PushButton self.connect_btn.clicked.connect(self.toggle_connection) - hbox.addWidget(QLabel("串口:")) + hbox.addWidget(BodyLabel("串口:")) hbox.addWidget(self.port_combo) - hbox.addWidget(QLabel("波特率:")) + hbox.addWidget(BodyLabel("波特率:")) hbox.addWidget(self.baud_combo) hbox.addWidget(self.connect_btn) layout.addLayout(hbox) @@ -82,15 +146,15 @@ class SerialTerminalInterface(BaseInterface): preset_group = QGroupBox("预设命令") preset_layout = QGridLayout() self.preset_commands = [ - ("复位", "RESET"), - ("获取版本", "GET_VERSION"), - ("启动", "START"), - ("停止", "STOP"), - ("自检", "SELF_TEST"), - ("查询状态", "STATUS?"), + ("线程监视器", "RESET"), + ("陀螺仪校准", "GET_VERSION"), + ("性能监视", "START"), + ("重启", "STOP"), + ("显示所有device", "SELF_TEST"), + ("查询id", "STATUS"), ] for i, (label, cmd) in enumerate(self.preset_commands): - btn = QPushButton(label) + btn = PushButton(label) # 替换QPushButton为PushButton btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) btn.clicked.connect(lambda _, c=cmd: self.send_preset_command(c)) preset_layout.addWidget(btn, i // 3, i % 3) @@ -98,19 +162,16 @@ class SerialTerminalInterface(BaseInterface): layout.addWidget(preset_group) # 显示区 - self.text_edit = QTextEdit() + self.text_edit = TextEdit() # 替换QTextEdit为TextEdit self.text_edit.setReadOnly(True) - self.text_edit.setStyleSheet( - "background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, 'Courier New', monospace; font-size: 14px;" - ) layout.addWidget(self.text_edit) # 输入区 input_hbox = QHBoxLayout() - self.input_line = QLineEdit() + self.input_line = LineEdit() self.input_line.setPlaceholderText("输入内容,回车发送") self.input_line.returnPressed.connect(self.send_data) - send_btn = QPushButton("发送") + send_btn = PushButton("发送") send_btn.clicked.connect(self.send_data) input_hbox.addWidget(self.input_line) input_hbox.addWidget(send_btn) @@ -168,13 +229,10 @@ class SerialTerminalInterface(BaseInterface): text = self.input_line.text() try: if not text: - # 内容为空,只发送换行 self.ser.write('\n'.encode()) else: - # 逐字符发送 for char in text: self.ser.write(char.encode()) - # 结尾加换行 self.ser.write('\n'.encode()) except Exception as e: self.text_edit.append(f"发送失败: {e}") @@ -182,12 +240,58 @@ class SerialTerminalInterface(BaseInterface): # ===================== 设置界面 ===================== class SettingInterface(BaseInterface): + themeSwitchRequested = pyqtSignal() + def __init__(self, parent=None): super().__init__(parent=parent) self.setObjectName("settingInterface") layout = QVBoxLayout() self.setLayout(layout) + # 标题 + layout.addSpacing(10) + layout.addWidget(SubtitleLabel("设置中心")) + layout.addSpacing(10) + layout.addWidget(HorizontalSeparator()) + + # 主题切换区域 + theme_title = StrongBodyLabel("外观设置") + theme_desc = BodyLabel("切换夜间/白天模式,适应不同环境。") + theme_desc.setWordWrap(True) + layout.addSpacing(10) + layout.addWidget(theme_title) + layout.addWidget(theme_desc) + + theme_box = QHBoxLayout() + self.theme_label = BodyLabel("夜间模式") + self.theme_switch = SwitchButton() + self.theme_switch.setChecked(Theme.DARK == Theme.DARK) + self.theme_switch.checkedChanged.connect(self.on_theme_switch) + theme_box.addWidget(self.theme_label) + theme_box.addWidget(self.theme_switch) + theme_box.addStretch() + layout.addLayout(theme_box) + + layout.addSpacing(15) + layout.addWidget(HorizontalSeparator()) + + # 其它设置区域(示例) + other_title = StrongBodyLabel("其它设置") + other_desc = BodyLabel("更多功能正在开发中,敬请期待。") + other_desc.setWordWrap(True) + layout.addSpacing(10) + layout.addWidget(other_title) + layout.addWidget(other_desc) + + # 版权信息 + layout.addStretch() + copyright_label = BodyLabel("© 2025 MRobot Toolbox") + copyright_label.setAlignment(Qt.AlignmentFlag.AlignHCenter) + layout.addWidget(copyright_label) + layout.addSpacing(10) + + def on_theme_switch(self, checked): + self.themeSwitchRequested.emit() # ===================== 帮助与关于界面 ===================== class HelpInterface(BaseInterface): def __init__(self, parent=None): @@ -213,11 +317,18 @@ class MainWindow(FluentWindow): self.resize(1000, 700) self.setMinimumSize(800, 600) + # 记录当前主题 + self.current_theme = Theme.DARK + + # 创建页面实例 + self.setting_page = SettingInterface(self) + self.setting_page.themeSwitchRequested.connect(self.toggle_theme) + self.page_registry = [ (HomeInterface(self), FIF.HOME, "首页", NavigationItemPosition.TOP), (DataInterface(self), FIF.LIBRARY, "MRobot代码生成", NavigationItemPosition.SCROLL), - (SerialTerminalInterface(self), FIF.COMMAND_PROMPT, "串口终端", NavigationItemPosition.SCROLL), - (SettingInterface(self), FIF.SETTING, "设置", NavigationItemPosition.BOTTOM), + (SerialTerminalInterface(self), FIF.COMMAND_PROMPT, "Mini_Shell", NavigationItemPosition.SCROLL), + (self.setting_page, FIF.SETTING, "设置", NavigationItemPosition.BOTTOM), (HelpInterface(self), FIF.HELP, "帮助", NavigationItemPosition.BOTTOM), (AboutInterface(self), FIF.INFO, "关于", NavigationItemPosition.BOTTOM), ] @@ -231,13 +342,32 @@ class MainWindow(FluentWindow): self.navigationInterface.addWidget( routeKey='avatar', widget=avatar, - onClick=None, + onClick=self.show_user_info, # 这里改为 self.show_user_info position=NavigationItemPosition.BOTTOM ) + def toggle_theme(self): + # 切换主题 + if self.current_theme == Theme.DARK: + self.current_theme = Theme.LIGHT + else: + self.current_theme = Theme.DARK + setTheme(self.current_theme) + # 同步设置界面按钮状态 + self.setting_page.theme_switch.setChecked(self.current_theme == Theme.DARK) + + def show_user_info(self): + dialog = Dialog( + title="用户信息", + content="用户:MRobot至尊VIP用户", + parent=self + ) + dialog.exec() + # ===================== 程序入口 ===================== def main(): app = QApplication(sys.argv) + setTheme(Theme.DARK) window = MainWindow() window.show() sys.exit(app.exec_())