mirror of
https://github.com/goldenfishs/MRobot.git
synced 2025-07-03 22:24:17 +08:00
完善MRUI架构
This commit is contained in:
parent
86b0062881
commit
b893c30eb3
180
MRobot.py
180
MRobot.py
@ -7,12 +7,22 @@ from PyQt5.QtGui import QTextCursor
|
|||||||
from PyQt5.QtCore import QThread, pyqtSignal
|
from PyQt5.QtCore import QThread, pyqtSignal
|
||||||
from PyQt5.QtWidgets import QHBoxLayout, QComboBox, QPushButton, QTextEdit, QLineEdit, QLabel
|
from PyQt5.QtWidgets import QHBoxLayout, QComboBox, QPushButton, QTextEdit, QLineEdit, QLabel
|
||||||
from PyQt5.QtWidgets import QGroupBox, QGridLayout, QSizePolicy
|
from PyQt5.QtWidgets import QGroupBox, QGridLayout, QSizePolicy
|
||||||
|
from qfluentwidgets import Theme, setTheme
|
||||||
from qfluentwidgets import (
|
from qfluentwidgets import (
|
||||||
NavigationItemPosition, Theme, FluentWindow, NavigationAvatarWidget,
|
NavigationItemPosition, Theme, FluentWindow, NavigationAvatarWidget,
|
||||||
PushButton, FluentIcon
|
PushButton, FluentIcon
|
||||||
)
|
)
|
||||||
from qfluentwidgets import FluentIcon as FIF
|
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):
|
class BaseInterface(QWidget):
|
||||||
@ -20,13 +30,67 @@ class BaseInterface(QWidget):
|
|||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
# ===================== 首页界面 =====================
|
# ===================== 首页界面 =====================
|
||||||
|
# ...existing code...
|
||||||
|
|
||||||
|
# ...existing code...
|
||||||
|
|
||||||
class HomeInterface(BaseInterface):
|
class HomeInterface(BaseInterface):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setObjectName("homeInterface")
|
self.setObjectName("homeInterface")
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
layout.setContentsMargins(60, 60, 60, 60)
|
||||||
|
layout.setSpacing(32)
|
||||||
self.setLayout(layout)
|
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):
|
class DataInterface(BaseInterface):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -65,15 +129,15 @@ class SerialTerminalInterface(BaseInterface):
|
|||||||
|
|
||||||
# 串口选择和连接
|
# 串口选择和连接
|
||||||
hbox = QHBoxLayout()
|
hbox = QHBoxLayout()
|
||||||
self.port_combo = QComboBox()
|
self.port_combo = ComboBox() # 替换QComboBox为ComboBox
|
||||||
self.refresh_ports()
|
self.refresh_ports()
|
||||||
self.baud_combo = QComboBox()
|
self.baud_combo = ComboBox() # 替换QComboBox为ComboBox
|
||||||
self.baud_combo.addItems(['9600', '115200', '57600', '38400', '19200', '4800'])
|
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)
|
self.connect_btn.clicked.connect(self.toggle_connection)
|
||||||
hbox.addWidget(QLabel("串口:"))
|
hbox.addWidget(BodyLabel("串口:"))
|
||||||
hbox.addWidget(self.port_combo)
|
hbox.addWidget(self.port_combo)
|
||||||
hbox.addWidget(QLabel("波特率:"))
|
hbox.addWidget(BodyLabel("波特率:"))
|
||||||
hbox.addWidget(self.baud_combo)
|
hbox.addWidget(self.baud_combo)
|
||||||
hbox.addWidget(self.connect_btn)
|
hbox.addWidget(self.connect_btn)
|
||||||
layout.addLayout(hbox)
|
layout.addLayout(hbox)
|
||||||
@ -82,15 +146,15 @@ class SerialTerminalInterface(BaseInterface):
|
|||||||
preset_group = QGroupBox("预设命令")
|
preset_group = QGroupBox("预设命令")
|
||||||
preset_layout = QGridLayout()
|
preset_layout = QGridLayout()
|
||||||
self.preset_commands = [
|
self.preset_commands = [
|
||||||
("复位", "RESET"),
|
("线程监视器", "RESET"),
|
||||||
("获取版本", "GET_VERSION"),
|
("陀螺仪校准", "GET_VERSION"),
|
||||||
("启动", "START"),
|
("性能监视", "START"),
|
||||||
("停止", "STOP"),
|
("重启", "STOP"),
|
||||||
("自检", "SELF_TEST"),
|
("显示所有device", "SELF_TEST"),
|
||||||
("查询状态", "STATUS?"),
|
("查询id", "STATUS"),
|
||||||
]
|
]
|
||||||
for i, (label, cmd) in enumerate(self.preset_commands):
|
for i, (label, cmd) in enumerate(self.preset_commands):
|
||||||
btn = QPushButton(label)
|
btn = PushButton(label) # 替换QPushButton为PushButton
|
||||||
btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||||
btn.clicked.connect(lambda _, c=cmd: self.send_preset_command(c))
|
btn.clicked.connect(lambda _, c=cmd: self.send_preset_command(c))
|
||||||
preset_layout.addWidget(btn, i // 3, i % 3)
|
preset_layout.addWidget(btn, i // 3, i % 3)
|
||||||
@ -98,19 +162,16 @@ class SerialTerminalInterface(BaseInterface):
|
|||||||
layout.addWidget(preset_group)
|
layout.addWidget(preset_group)
|
||||||
|
|
||||||
# 显示区
|
# 显示区
|
||||||
self.text_edit = QTextEdit()
|
self.text_edit = TextEdit() # 替换QTextEdit为TextEdit
|
||||||
self.text_edit.setReadOnly(True)
|
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)
|
layout.addWidget(self.text_edit)
|
||||||
|
|
||||||
# 输入区
|
# 输入区
|
||||||
input_hbox = QHBoxLayout()
|
input_hbox = QHBoxLayout()
|
||||||
self.input_line = QLineEdit()
|
self.input_line = LineEdit()
|
||||||
self.input_line.setPlaceholderText("输入内容,回车发送")
|
self.input_line.setPlaceholderText("输入内容,回车发送")
|
||||||
self.input_line.returnPressed.connect(self.send_data)
|
self.input_line.returnPressed.connect(self.send_data)
|
||||||
send_btn = QPushButton("发送")
|
send_btn = PushButton("发送")
|
||||||
send_btn.clicked.connect(self.send_data)
|
send_btn.clicked.connect(self.send_data)
|
||||||
input_hbox.addWidget(self.input_line)
|
input_hbox.addWidget(self.input_line)
|
||||||
input_hbox.addWidget(send_btn)
|
input_hbox.addWidget(send_btn)
|
||||||
@ -168,13 +229,10 @@ class SerialTerminalInterface(BaseInterface):
|
|||||||
text = self.input_line.text()
|
text = self.input_line.text()
|
||||||
try:
|
try:
|
||||||
if not text:
|
if not text:
|
||||||
# 内容为空,只发送换行
|
|
||||||
self.ser.write('\n'.encode())
|
self.ser.write('\n'.encode())
|
||||||
else:
|
else:
|
||||||
# 逐字符发送
|
|
||||||
for char in text:
|
for char in text:
|
||||||
self.ser.write(char.encode())
|
self.ser.write(char.encode())
|
||||||
# 结尾加换行
|
|
||||||
self.ser.write('\n'.encode())
|
self.ser.write('\n'.encode())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.text_edit.append(f"发送失败: {e}")
|
self.text_edit.append(f"发送失败: {e}")
|
||||||
@ -182,12 +240,58 @@ class SerialTerminalInterface(BaseInterface):
|
|||||||
|
|
||||||
# ===================== 设置界面 =====================
|
# ===================== 设置界面 =====================
|
||||||
class SettingInterface(BaseInterface):
|
class SettingInterface(BaseInterface):
|
||||||
|
themeSwitchRequested = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setObjectName("settingInterface")
|
self.setObjectName("settingInterface")
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
self.setLayout(layout)
|
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):
|
class HelpInterface(BaseInterface):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -213,11 +317,18 @@ class MainWindow(FluentWindow):
|
|||||||
self.resize(1000, 700)
|
self.resize(1000, 700)
|
||||||
self.setMinimumSize(800, 600)
|
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 = [
|
self.page_registry = [
|
||||||
(HomeInterface(self), FIF.HOME, "首页", NavigationItemPosition.TOP),
|
(HomeInterface(self), FIF.HOME, "首页", NavigationItemPosition.TOP),
|
||||||
(DataInterface(self), FIF.LIBRARY, "MRobot代码生成", NavigationItemPosition.SCROLL),
|
(DataInterface(self), FIF.LIBRARY, "MRobot代码生成", NavigationItemPosition.SCROLL),
|
||||||
(SerialTerminalInterface(self), FIF.COMMAND_PROMPT, "串口终端", NavigationItemPosition.SCROLL),
|
(SerialTerminalInterface(self), FIF.COMMAND_PROMPT, "Mini_Shell", NavigationItemPosition.SCROLL),
|
||||||
(SettingInterface(self), FIF.SETTING, "设置", NavigationItemPosition.BOTTOM),
|
(self.setting_page, FIF.SETTING, "设置", NavigationItemPosition.BOTTOM),
|
||||||
(HelpInterface(self), FIF.HELP, "帮助", NavigationItemPosition.BOTTOM),
|
(HelpInterface(self), FIF.HELP, "帮助", NavigationItemPosition.BOTTOM),
|
||||||
(AboutInterface(self), FIF.INFO, "关于", NavigationItemPosition.BOTTOM),
|
(AboutInterface(self), FIF.INFO, "关于", NavigationItemPosition.BOTTOM),
|
||||||
]
|
]
|
||||||
@ -231,13 +342,32 @@ class MainWindow(FluentWindow):
|
|||||||
self.navigationInterface.addWidget(
|
self.navigationInterface.addWidget(
|
||||||
routeKey='avatar',
|
routeKey='avatar',
|
||||||
widget=avatar,
|
widget=avatar,
|
||||||
onClick=None,
|
onClick=self.show_user_info, # 这里改为 self.show_user_info
|
||||||
position=NavigationItemPosition.BOTTOM
|
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():
|
def main():
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
setTheme(Theme.DARK)
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
window.show()
|
window.show()
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
Loading…
Reference in New Issue
Block a user