diff --git a/ui/main_window.py b/ui/main_window.py index 4511ae63..fac34bda 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -3659,22 +3659,37 @@ class MainWindow(QMainWindow): if hasattr(self.world,'gui_manager') and self.world.gui_manager: self.world.gui_manager.createCesiumView() else: - QMessageBox.warning(self,"错误","GUI管理其不可用") - + UniversalMessageDialog.show_warning( + self, + "错误", + "GUI管理器不可用", + show_cancel=False, + confirm_text="确认" + ) def onToggleCesiumView(self): """切换 Cesium 视图显示状态""" if hasattr(self.world, 'gui_manager') and self.world.gui_manager: self.world.gui_manager.toggleCesiumView() else: - QMessageBox.warning(self, "错误", "GUI 管理器不可用") - + UniversalMessageDialog.show_warning( + self, + "错误", + "GUI 管理器不可用", + show_cancel=False, + confirm_text="确认" + ) def onRefreshCesiumView(self): """刷新 Cesium 视图""" if hasattr(self.world, 'gui_manager') and self.world.gui_manager: self.world.gui_manager.refreshCesiumView() else: - QMessageBox.warning(self, "错误", "GUI 管理器不可用") - + UniversalMessageDialog.show_warning( + self, + "错误", + "GUI 管理器不可用", + show_cancel=False, + confirm_text="确认" + ) def onUpdateCesiumURL(self): """更新 Cesium URL""" dialog = self.createStyledInputDialog( @@ -3690,7 +3705,13 @@ class MainWindow(QMainWindow): if hasattr(self.world, 'gui_manager') and self.world.gui_manager: self.world.gui_manager.updateCesiumURL(url) else: - QMessageBox.warning(self, "错误", "GUI 管理器不可用") + UniversalMessageDialog.show_warning( + self, + "错误", + "GUI 管理器不可用", + show_cancel=False, + confirm_text="确认" + ) def onAddModelClicked(self): @@ -4121,7 +4142,7 @@ class MainWindow(QMainWindow): print(f"✗ 创建3D示例天气信息面板失败: {e}") import traceback traceback.print_exc() - QMessageBox.critical(self, "错误", f"创建3D示例天气信息面板时出错: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"创建3D示例天气信息面板时出错: {str(e)}") # 更新 addInfoPanelToTree 方法以支持3D面板 def addInfoPanelToTree(self, panel, panel_name): @@ -4198,7 +4219,7 @@ class MainWindow(QMainWindow): print(f"✗ 创建系统状态信息面板失败: {e}") import traceback traceback.print_exc() - QMessageBox.critical(self, "错误", f"创建系统状态信息面板时出错: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"创建系统状态信息面板时出错: {str(e)}") def getSystemStatusData(self): """ @@ -4275,7 +4296,7 @@ class MainWindow(QMainWindow): print(f"✗ 创建传感器数据信息面板失败: {e}") import traceback traceback.print_exc() - QMessageBox.critical(self, "错误", f"创建传感器数据信息面板时出错: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"创建传感器数据信息面板时出错: {str(e)}") def getSensorData(self): """ @@ -4339,7 +4360,7 @@ class MainWindow(QMainWindow): print(f"✗ 创建场景信息面板失败: {e}") import traceback traceback.print_exc() - QMessageBox.critical(self, "错误", f"创建场景信息面板时出错: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"创建场景信息面板时出错: {str(e)}") def getSceneInfoData(self): """ @@ -4786,7 +4807,7 @@ class MainWindow(QMainWindow): print("🎨 图标管理器已打开") except Exception as e: print(f"❌ 打开图标管理器失败: {e}") - QMessageBox.warning(self, "错误", f"打开图标管理器失败:\n{str(e)}") + UniversalMessageDialog.show_warning(self, "警告", f"打开图标管理器失败: {str(e)}", show_cancel=False, confirm_text="确认") def closeEvent(self, event): """处理窗口关闭事件""" @@ -4977,7 +4998,7 @@ class MainWindow(QMainWindow): config_dialog = AssemblyDisassemblyConfigDialog(self, self.world) config_dialog.show() except Exception as e: - QMessageBox.critical(self, "错误", f"打开拆装配置界面失败: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"打开拆装配置界面失败: {str(e)}") import traceback traceback.print_exc() @@ -5002,7 +5023,7 @@ class MainWindow(QMainWindow): self.world.assembly_interaction.start_interaction_mode(mode=selected_mode) except Exception as e: - QMessageBox.critical(self, "错误", f"启动拆装交互失败: {str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"启动拆装交互失败: {str(e)}") import traceback traceback.print_exc() @@ -5057,11 +5078,11 @@ class MainWindow(QMainWindow): print(f"✅ 维修科目启动成功") else: print("❌ 维修科目启动失败") - QMessageBox.warning(self, "错误", "维修科目启动失败") + UniversalMessageDialog.show_warning(self, "错误", "维修科目启动失败",False,"确认") except Exception as e: print(f"❌ 启动维修科目失败: {e}") - QMessageBox.critical(self, "错误", f"启动维修科目失败:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"启动维修科目失败: {str(e)}") import traceback traceback.print_exc() @@ -5073,7 +5094,7 @@ class MainWindow(QMainWindow): except Exception as e: print(f"❌ 打开维修系统失败: {e}") - QMessageBox.critical(self, "错误", f"打开维修系统失败:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"打开维修系统失败: {str(e)}") import traceback traceback.print_exc() @@ -5090,14 +5111,21 @@ class MainWindow(QMainWindow): # 更新菜单状态 self.enterVRAction.setEnabled(False) self.exitVRAction.setEnabled(True) - QMessageBox.information(self, "成功", "VR模式已启用!\n请确保您的VR头显已正确连接。") + UniversalMessageDialog.show_info( + self, "成功", "VR模式已启用!\n请确保您的VR头显已正确连接。" + , False, "确认") else: - QMessageBox.warning(self, "错误", "无法启用VR模式!\n请检查:\n1. SteamVR是否正在运行\n2. VR头显是否已连接\n3. OpenVR库是否已正确安装") + UniversalMessageDialog.show_warning( + self, "错误", "无法启用VR模式!\n请检查:\n1. SteamVR是否正在运行\n2. VR头显是否已连接\n3. OpenVR库是否已正确安装" + , False, "确认") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning( + self, "错误", "VR管理器不可用!" + , False, "确认") except Exception as e: - QMessageBox.critical(self, "错误", f"启用VR模式时发生错误:\n{str(e)}") - + UniversalMessageDialog.show_error( + self, "错误", f"启用VR模式时发生错误:\n{str(e)}" + , False, "确认") def onExitVR(self): """退出VR模式""" try: @@ -5106,11 +5134,14 @@ class MainWindow(QMainWindow): # 更新菜单状态 self.enterVRAction.setEnabled(True) self.exitVRAction.setEnabled(False) - QMessageBox.information(self, "成功", "已退出VR模式") + UniversalMessageDialog.show_info(self, "成功", "已退出VR模式" + , False, "确认") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!" + , False, "确认") except Exception as e: - QMessageBox.critical(self, "错误", f"退出VR模式时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"退出VR模式时发生错误:\n{str(e)}" + , False, "确认") def onShowVRStatus(self): """显示VR状态""" @@ -5130,12 +5161,14 @@ class MainWindow(QMainWindow): - 如果VR不可用,请确保已安装SteamVR并连接VR头显 - 如果OpenVR库未安装,请运行:pip install openvr """ - - QMessageBox.information(self, "VR状态", status_text) + UniversalMessageDialog.show_info(self, "VR状态", status_text + , False, "确认") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!" + , False, "确认") except Exception as e: - QMessageBox.critical(self, "错误", f"获取VR状态时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"获取VR状态时发生错误:\n{str(e)}" + , False, "确认") def onShowVRSettings(self): """显示VR设置对话框""" @@ -5144,149 +5177,301 @@ class MainWindow(QMainWindow): dialog = self.createVRSettingsDialog() dialog.exec_() else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!" + , False, "确认") except Exception as e: - QMessageBox.critical(self, "错误", f"打开VR设置时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"打开VR设置时发生错误:\n{str(e)}" + , False, "确认") def createVRSettingsDialog(self): - """创建VR设置对话框""" + """创建VR设置对话框(统一为 NewProjectDialog 风格)""" dialog = QDialog(self) dialog.setWindowTitle("VR设置") dialog.setModal(True) - dialog.resize(400, 300) + dialog.resize(508, 420) + dialog.setObjectName("newProjectDialog") + dialog.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint) + dialog.setAttribute(Qt.WA_TranslucentBackground, True) - layout = QVBoxLayout(dialog) + dialog.setStyleSheet(""" + QDialog#newProjectDialog { background-color: transparent; color: #EBEBEB; border: none; } + QFrame#baseFrame { background-color: #000000; border: 1px solid #3E3E42; border-radius: 5px; } + QWidget#titleBar { background-color: transparent; border: none; border-radius: 5px 5px 0 0; min-height: 32px; max-height: 32px; } + QWidget#titleBar QWidget { background-color: transparent; border: none; } + QLabel#titleLabel { color: #FFFFFF; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 14px; font-weight: 500; letter-spacing: 0.7px; } + QWidget#controlButtons QPushButton { background-color: transparent; border: none; color: #EBEBEB; font-size: 14px; min-width: 18px; max-width: 18px; min-height: 18px; max-height: 18px; padding: 0px; border-radius: 3px; } + QWidget#controlButtons QPushButton:hover { background-color: #2A2D2E; color: #FFFFFF; } + QPushButton#closeButton { border-radius: 0px 5px 0px 0px; } + QPushButton#closeButton:hover { background-color: #2A2D2E; color: #FFFFFF; } + QWidget#contentWidget { background-color: transparent; border-radius: 0 0 5px 5px; } + QFrame#contentContainer { background-color: #19191B; border: 1px solid #2C2F36; border-radius: 5px; } + QLabel[role="sectionTitle"] { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 12px; font-weight: 500; letter-spacing: 0.6px; } + QLabel[role="fieldLabel"] { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 12px; font-weight: 400; letter-spacing: 0.6px; } + QLabel { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; letter-spacing: 0.55px; } + QComboBox, QSpinBox, QDoubleSpinBox { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; } + QCheckBox { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; } + QLineEdit { background-color: rgba(89,100,113,0.2); color: #EBEBEB; border: 1px solid rgba(76,92,110,0.6); border-radius: 2px; padding: 6px 10px; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; letter-spacing: 0.55px; min-height: 14px; max-height: 30px; } + QLineEdit:focus { border: 1px solid #3067C0; background-color: rgba(48,103,192,0.1); } + QLineEdit:hover { border: 1px solid #3067C0; background-color: rgba(89,100,113,0.3); } + QLineEdit:disabled { background-color: rgba(89,100,113,0.1); color: rgba(235,235,235,0.4); border: 1px solid rgba(76,92,110,0.2); } + QTextEdit { background-color: rgba(89,100,113,0.1); color: #EBEBEB; border: 1px solid rgba(76,92,110,0.4); border-radius: 4px; font-size: 11px; } + QPushButton { background-color: rgba(89,98,118,0.5); color: #EBEBEB; border: none; border-radius: 2px; padding: 0px 0px; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-weight: 300; font-size: 10px; letter-spacing: 0.5px; min-width: 90px; min-height: 30px; max-height: 30px; } + QPushButton:hover { background-color: #3067C0; color: #FFFFFF; } + QPushButton:pressed { background-color: #2556A0; color: #FFFFFF; } + QPushButton:disabled { background-color: rgba(89,98,118,0.3); color: rgba(235,235,235,0.4); } + QPushButton#primaryButton { background-color: rgba(89,98,118,0.5); border: none; color: #EBEBEB; font-weight: 300; min-width: 120px; max-width: 120px; } + QPushButton#primaryButton:hover { background-color: #2556A0; } + QPushButton#primaryButton:pressed { background-color: #1E4A8C; } + """) - # VR状态显示 - status_group = QGroupBox("VR状态") - status_layout = QVBoxLayout() + main_layout = QVBoxLayout(dialog) + main_layout.setContentsMargins(0, 0, 0, 0) + main_layout.setSpacing(0) + base_frame = QFrame() + base_frame.setObjectName('baseFrame') + base_frame.setFrameShape(QFrame.NoFrame) + base_frame.setAttribute(Qt.WA_StyledBackground, True) + base_layout = QVBoxLayout(base_frame) + base_layout.setContentsMargins(0, 0, 0, 0) + base_layout.setSpacing(0) + + # Title bar + title_bar = QWidget() + title_bar.setObjectName('titleBar') + tb_layout = QHBoxLayout(title_bar) + tb_layout.setContentsMargins(8, 0, 8, 0) + tb_layout.setSpacing(6) + control_buttons = QWidget() + control_buttons.setObjectName('controlButtons') + cb_layout = QHBoxLayout(control_buttons) + cb_layout.setContentsMargins(0, 0, 0, 0) + cb_layout.setSpacing(0) + close_btn = QPushButton() + close_btn.setObjectName('closeButton') + try: + close_btn.setIcon(get_icon('close_icon', QSize(18, 18))) + close_btn.setIconSize(QSize(18, 18)) + except Exception: + pass + close_btn.clicked.connect(dialog.reject) + cb_layout.addWidget(close_btn) + left_placeholder = QWidget() + left_placeholder.setFixedWidth(control_buttons.sizeHint().width()) + tb_layout.addWidget(left_placeholder) + title_label = QLabel("VR设置") + title_label.setObjectName('titleLabel') + title_label.setAlignment(Qt.AlignCenter) + tb_layout.addWidget(title_label, 1) + tb_layout.addWidget(control_buttons) + base_layout.addWidget(title_bar) + + # drag handlers + dragging_state = {'dragging': False, 'pos': QPoint()} + def _tb_press(event): + if event.button() == Qt.LeftButton: + dragging_state['dragging'] = True + dragging_state['pos'] = event.globalPos() - dialog.frameGeometry().topLeft() + event.accept() + else: + event.ignore() + def _tb_move(event): + if event.buttons() & Qt.LeftButton and dragging_state['dragging']: + dialog.move(event.globalPos() - dragging_state['pos']) + event.accept() + else: + event.ignore() + def _tb_release(event): + if event.button() == Qt.LeftButton: + dragging_state['dragging'] = False + event.accept() + else: + event.ignore() + title_bar.mousePressEvent = _tb_press + title_bar.mouseMoveEvent = _tb_move + title_bar.mouseReleaseEvent = _tb_release + + # Content + content_widget = QWidget() + content_widget.setObjectName('contentWidget') + content_layout = QVBoxLayout(content_widget) + content_layout.setContentsMargins(10, 10, 10, 10) + content_layout.setSpacing(0) + + content_container = QFrame() + content_container.setObjectName('contentContainer') + content_container.setFrameShape(QFrame.NoFrame) + content_container.setAttribute(Qt.WA_StyledBackground, True) + container_layout = QVBoxLayout(content_container) + container_layout.setContentsMargins(15, 10, 15, 10) + container_layout.setSpacing(10) + + # 左侧对齐辅助:统一字段列宽,并让小标题与控件左侧对齐 + label_column_width = 110 + def add_section_title(text): + title = QLabel(text) + title.setProperty('role', 'sectionTitle') + container_layout.addWidget(title) + + # VR 状态 + add_section_title("VR状态") + status_widget = QWidget() + status_vlayout = QVBoxLayout(status_widget) + status_vlayout.setContentsMargins(0, 0, 0, 0) + status_vlayout.setSpacing(6) if hasattr(self.world, 'vr_manager') and self.world.vr_manager: status = self.world.vr_manager.get_vr_status() - available_label = QLabel(f"VR可用性: {'是' if status['available'] else '否'}") - available_label.setStyleSheet(f"color: {'green' if status['available'] else 'red'};") - status_layout.addWidget(available_label) - + available_label.setStyleSheet(f"color: {'#2dffc4' if status['available'] else 'red'};") + status_vlayout.addWidget(available_label) enabled_label = QLabel(f"VR状态: {'已启用' if status['enabled'] else '未启用'}") - enabled_label.setStyleSheet(f"color: {'green' if status['enabled'] else 'gray'};") - status_layout.addWidget(enabled_label) - + enabled_label.setStyleSheet(f"color: {'#2dffc4' if status['enabled'] else 'gray'};") + status_vlayout.addWidget(enabled_label) resolution_label = QLabel(f"渲染分辨率: {status['eye_resolution'][0]}x{status['eye_resolution'][1]}") - status_layout.addWidget(resolution_label) + status_vlayout.addWidget(resolution_label) + container_layout.addWidget(status_widget) - status_group.setLayout(status_layout) - layout.addWidget(status_group) - - # 🎨 渲染模式设置 - render_mode_group = QGroupBox("渲染模式") - render_mode_layout = QVBoxLayout() - - # 创建单选按钮组 + # 渲染模式 + add_section_title("渲染模式") render_mode_button_group = QButtonGroup(dialog) - + row_mode1 = QWidget(); row_mode1_layout = QHBoxLayout(row_mode1); row_mode1_layout.setContentsMargins(0,0,0,0); row_mode1_layout.setSpacing(10) normal_render_radio = QRadioButton("普通渲染模式") + normal_render_radio.setStyleSheet(""" + QRadioButton { + color: #EBEBEB; + font-family: 'Inter', 'Microsoft YaHei', sans-serif; + font-size: 12px; + font-weight: 400; + letter-spacing: 0.6px; + } + """) + row_mode1_layout.addWidget(normal_render_radio) + row_mode1_layout.addStretch(); container_layout.addWidget(row_mode1) + row_mode2 = QWidget(); row_mode2_layout = QHBoxLayout(row_mode2); row_mode2_layout.setContentsMargins(0,0,0,0); row_mode2_layout.setSpacing(10) pipeline_render_radio = QRadioButton("RenderPipeline高级渲染(推荐)") - + pipeline_render_radio.setStyleSheet(""" + QRadioButton { + color: #EBEBEB; + font-family: 'Inter', 'Microsoft YaHei', sans-serif; + font-size: 12px; + font-weight: 400; + letter-spacing: 0.6px; + } + """) + row_mode2_layout.addWidget(pipeline_render_radio) + row_mode2_layout.addStretch(); container_layout.addWidget(row_mode2) render_mode_button_group.addButton(normal_render_radio, 0) render_mode_button_group.addButton(pipeline_render_radio, 1) - - # 根据当前模式设置选中状态 if hasattr(self.world, 'vr_manager') and self.world.vr_manager: - from core.vr import VRRenderMode - current_mode = self.world.vr_manager.get_vr_render_mode() - if current_mode == VRRenderMode.RENDER_PIPELINE: - pipeline_render_radio.setChecked(True) - else: + try: + from core.vr import VRRenderMode + current_mode = self.world.vr_manager.get_vr_render_mode() + if current_mode == VRRenderMode.RENDER_PIPELINE: + pipeline_render_radio.setChecked(True) + else: + normal_render_radio.setChecked(True) + except Exception: normal_render_radio.setChecked(True) else: normal_render_radio.setChecked(True) - - render_mode_layout.addWidget(normal_render_radio) - render_mode_layout.addWidget(pipeline_render_radio) - - # 添加说明文本 info_text = QTextEdit() info_text.setReadOnly(True) info_text.setMaximumHeight(60) - info_text.setPlainText( - "• 普通渲染:性能最优,适合低配置\n" - "• RenderPipeline:高级图形效果(阴影、AO等),需要较高性能" - ) - render_mode_layout.addWidget(info_text) - - render_mode_group.setLayout(render_mode_layout) - layout.addWidget(render_mode_group) - - # 保存按钮组引用以便后续使用 + info_text.setPlainText("• 普通渲染:性能最优,适合低配置\n• RenderPipeline:高级图形效果(阴影、AO等),需要较高性能") + container_layout.addWidget(info_text) dialog.render_mode_button_group = render_mode_button_group - # 🔧 加载配置 + # 载入配置 vr_config = {} if hasattr(self.world, 'vr_manager') and self.world.vr_manager and self.world.vr_manager.config_manager: vr_config = self.world.vr_manager.config_manager.load_config() # 渲染设置 - render_group = QGroupBox("渲染设置") - render_layout = QFormLayout() - - # 渲染质量 + add_section_title("渲染设置") + row_quality = QWidget() + row_quality_layout = QHBoxLayout(row_quality) + row_quality_layout.setContentsMargins(0,0,0,0) + row_quality_layout.setSpacing(10) + quality_label = QLabel("渲染质量:") + quality_label.setProperty('role','fieldLabel') + quality_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_quality_layout.addWidget(quality_label) quality_combo = QComboBox() - quality_combo.addItems(["低", "中", "高"]) - # 从配置加载质量预设 + quality_combo.addItems(["低","中","高"]) quality_preset = vr_config.get("quality_preset", "balanced") - quality_map = {"performance": "低", "balanced": "中", "quality": "高"} - quality_combo.setCurrentText(quality_map.get(quality_preset, "中")) - render_layout.addRow("渲染质量:", quality_combo) - - # 抗锯齿 + quality_map={"performance":"低","balanced":"中","quality":"高"} + quality_combo.setCurrentText(quality_map.get(quality_preset,"中")) + row_quality_layout.addWidget(quality_combo,1) + container_layout.addWidget(row_quality) + row_aa = QWidget(); row_aa_layout = QHBoxLayout(row_aa) + row_aa_layout.setContentsMargins(0,0,0,0) + row_aa_layout.setSpacing(10) + aa_label = QLabel("抗锯齿:") + aa_label.setProperty('role','fieldLabel') + aa_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_aa_layout.addWidget(aa_label) aa_combo = QComboBox() - aa_combo.addItems(["无", "2x", "4x", "8x"]) - aa_combo.setCurrentText(vr_config.get("anti_aliasing", "4x")) - render_layout.addRow("抗锯齿:", aa_combo) - - render_group.setLayout(render_layout) - layout.addWidget(render_group) + aa_combo.addItems(["无","2x","4x","8x"]) + aa_combo.setCurrentText(vr_config.get("anti_aliasing","4x")) + row_aa_layout.addWidget(aa_combo,1) + container_layout.addWidget(row_aa) # 性能设置 - perf_group = QGroupBox("性能设置") - perf_layout = QFormLayout() - - # 刷新率 + add_section_title("性能设置") + row_refresh = QWidget() + row_refresh_layout = QHBoxLayout(row_refresh) + row_refresh_layout.setContentsMargins(0,0,0,0) + row_refresh_layout.setSpacing(10) + refresh_label = QLabel("刷新率:") + refresh_label.setProperty('role','fieldLabel') + refresh_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_refresh_layout.addWidget(refresh_label) refresh_combo = QComboBox() - refresh_combo.addItems(["72Hz", "90Hz", "120Hz", "144Hz"]) - refresh_combo.setCurrentText(vr_config.get("refresh_rate", "90Hz")) - perf_layout.addRow("刷新率:", refresh_combo) - - # 异步重投影 + refresh_combo.addItems(["72Hz","90Hz","120Hz","144Hz"]) + refresh_combo.setCurrentText(vr_config.get("refresh_rate","90Hz")) + row_refresh_layout.addWidget(refresh_combo,1) + container_layout.addWidget(row_refresh) + row_async = QWidget() + row_async_layout = QHBoxLayout(row_async) + row_async_layout.setContentsMargins(0,0,0,0) + row_async_layout.setSpacing(10) async_check = QCheckBox("启用异步重投影") - async_check.setChecked(vr_config.get("async_reprojection", True)) - perf_layout.addRow("", async_check) + async_check.setChecked(vr_config.get("async_reprojection",True)) + row_async_layout.addWidget(async_check) + row_async_layout.addStretch() + container_layout.addWidget(row_async) - perf_group.setLayout(perf_layout) - layout.addWidget(perf_group) - - # 保存控件引用到dialog对象 + # Save refs dialog.quality_combo = quality_combo dialog.aa_combo = aa_combo dialog.refresh_combo = refresh_combo dialog.async_check = async_check - # 按钮 - button_layout = QHBoxLayout() + # Separator before buttons + separator_buttons = QFrame() + separator_buttons.setFrameShape(QFrame.HLine) + separator_buttons.setFrameShadow(QFrame.Plain) + separator_buttons.setFixedHeight(1) + separator_buttons.setStyleSheet("background-color: #2C2F36; border: none;") + container_layout.addWidget(separator_buttons) + # Buttons + button_layout = QHBoxLayout() apply_button = QPushButton("应用") ok_button = QPushButton("确定") + # ok_button.setObjectName("primaryButton") cancel_button = QPushButton("取消") - button_layout.addWidget(apply_button) button_layout.addStretch() button_layout.addWidget(ok_button) button_layout.addWidget(cancel_button) + container_layout.addLayout(button_layout) - layout.addLayout(button_layout) + content_layout.addWidget(content_container, 0, Qt.AlignTop) + base_layout.addWidget(content_widget) + main_layout.addWidget(base_frame) - # 连接信号 + # signals apply_button.clicked.connect(lambda: self.applyVRSettings(dialog)) ok_button.clicked.connect(lambda: self.onVRSettingsOK(dialog)) cancel_button.clicked.connect(dialog.reject) @@ -5304,11 +5489,11 @@ class MainWindow(QMainWindow): """应用VR设置""" try: if not hasattr(self.world, 'vr_manager') or not self.world.vr_manager: - QMessageBox.warning(dialog, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(dialog, "错误", "VR管理器不可用!",False,"确定") return if not self.world.vr_manager.config_manager: - QMessageBox.warning(dialog, "错误", "VR配置管理器不可用!") + UniversalMessageDialog.show_warning(dialog, "错误", "VR配置管理器不可用!",False,"确定") return # 1️⃣ 读取所有UI控件的值 @@ -5343,25 +5528,21 @@ class MainWindow(QMainWindow): # 5️⃣ 如果渲染模式改变,询问用户确认 if mode_changed: - reply = QMessageBox.question( - dialog, - "确认切换", - f"确定要切换到{mode_name}模式吗?\n\n注意:切换渲染模式将重新创建VR缓冲区,可能需要几秒钟。", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No - ) + reply = UniversalMessageDialog.show_info(dialog, "确认切换", f"确定要切换到{mode_name}模式吗?\n\n注意:切换渲染模式将重新创建VR缓冲区,可能需要几秒钟。",True,"取消","确定") - if reply == QMessageBox.No: + if reply == QDialog.Rejected: # 用户取消渲染模式切换,但仍然保存其他设置 self.world.vr_manager.config_manager.save_config(config) - QMessageBox.information(dialog, "提示", "已保存其他设置(未切换渲染模式)") + UniversalMessageDialog.show_info(dialog, "提示", "已保存其他设置(未切换渲染模式)", + False, "确定") return # 应用渲染模式切换 success = self.world.vr_manager.set_vr_render_mode(new_mode) if not success: - QMessageBox.warning(dialog, "失败", f"切换到{mode_name}模式失败!\n请查看控制台输出了解详情。") + UniversalMessageDialog.show_warning(dialog, "失败", f"切换到{mode_name}模式失败!\n请查看控制台输出了解详情。", + False, "确定") return # 6️⃣ 保存配置(如果模式改变,set_vr_render_mode已经保存了,但我们需要确保其他设置也被保存) @@ -5373,12 +5554,15 @@ class MainWindow(QMainWindow): # 8️⃣ 显示成功消息 if mode_changed: - QMessageBox.information(dialog, "成功", f"VR设置已应用!\n• 渲染模式: {mode_name}\n• 渲染质量: {quality_text}\n配置已自动保存。") + UniversalMessageDialog.show_info(dialog, "成功", f"VR设置已应用!\n• 渲染模式: {mode_name}\n• 渲染质量: {quality_text}\n配置已自动保存。", + False, "确定") else: - QMessageBox.information(dialog, "成功", f"VR设置已保存!\n• 渲染质量: {quality_text}") + UniversalMessageDialog.show_info(dialog, "成功", f"VR设置已保存!\n• 渲染质量: {quality_text}", + False, "确定") except Exception as e: - QMessageBox.critical(dialog, "错误", f"应用VR设置时发生错误:\n{str(e)}") + UniversalMessageDialog.show_critical(dialog, "错误", f"应用VR设置时发生错误:\n{str(e)}", + False, "确定") import traceback traceback.print_exc() @@ -5392,11 +5576,14 @@ class MainWindow(QMainWindow): self.vrDebugToggleAction.setChecked(enabled) status = "启用" if enabled else "禁用" - QMessageBox.information(self, "VR调试", f"VR调试输出已{status}") + UniversalMessageDialog.show_info(self, "提示", f"已{status}VR调试输出", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"切换VR调试时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"切换VR调试时发生错误:\n{str(e)}", + False, "确定") def onShowVRPerformance(self): """立即显示VR性能报告""" @@ -5404,13 +5591,17 @@ class MainWindow(QMainWindow): if hasattr(self.world, 'vr_manager') and self.world.vr_manager: if self.world.vr_manager.vr_enabled: self.world.vr_manager.force_performance_report() - QMessageBox.information(self, "VR性能", "性能报告已输出到控制台") + UniversalMessageDialog.show_info(self, "提示", "已立即显示VR性能报告", + False, "确定") else: - QMessageBox.warning(self, "提示", "请先启用VR模式") + UniversalMessageDialog.show_warning(self, "提示", "请先启用VR模式", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"显示VR性能报告时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"显示VR性能报告时发生错误:\n{str(e)}", + False, "确定") def onSetVRDebugMode(self, mode): """设置VR调试模式""" @@ -5427,11 +5618,14 @@ class MainWindow(QMainWindow): self.vrDebugDetailedAction.setChecked(True) mode_name = "简短" if mode == 'brief' else "详细" - QMessageBox.information(self, "VR调试", f"调试模式已设置为:{mode_name}") + UniversalMessageDialog.show_info(self, "提示", f"已设置VR调试模式为:{mode_name}", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"设置VR调试模式时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"设置VR调试模式时发生错误:\n{str(e)}", + False, "确定") def onToggleVRPerformanceMonitor(self): """切换VR性能监控""" @@ -5444,12 +5638,15 @@ class MainWindow(QMainWindow): self.world.vr_manager.disable_performance_monitoring() status = "启用" if enabled else "禁用" - QMessageBox.information(self, "VR性能监控", f"VR性能监控已{status}") + UniversalMessageDialog.show_info(self, "提示", f"已{status}VR性能监控", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") self.vrPerformanceMonitorAction.setChecked(False) except Exception as e: - QMessageBox.critical(self, "错误", f"切换VR性能监控时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"切换VR性能监控时发生错误:\n{str(e)}", + False, "确定") def onToggleVRGpuTiming(self): """切换VR GPU时间监控""" @@ -5462,12 +5659,15 @@ class MainWindow(QMainWindow): self.world.vr_manager.disable_gpu_timing_monitoring() status = "启用" if enabled else "禁用" - QMessageBox.information(self, "VR GPU监控", f"VR GPU时间监控已{status}") + UniversalMessageDialog.show_info(self, "提示", f"已{status}VR GPU时间监控", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") self.vrGpuTimingAction.setChecked(False) except Exception as e: - QMessageBox.critical(self, "错误", f"切换VR GPU时间监控时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"切换VR GPU时间监控时发生错误:\n{str(e)}", + False, "确定") def onToggleVRPipelineMonitor(self): """切换VR管线监控""" @@ -5478,10 +5678,12 @@ class MainWindow(QMainWindow): status = "启用" if enabled else "禁用" print(f"✓ VR管线监控已{status}") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") self.vrPipelineMonitorAction.setChecked(False) except Exception as e: - QMessageBox.critical(self, "错误", f"切换VR管线监控时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"切换VR管线监控时发生错误:\n{str(e)}", + False, "确定") def onSetVRPoseStrategy(self, strategy): """设置VR姿态策略""" @@ -5493,25 +5695,31 @@ class MainWindow(QMainWindow): 'render_callback': '渲染回调策略', 'update_task': '更新任务策略' } - QMessageBox.information(self, "VR姿态策略", - f"姿态策略已切换为:{strategy_names.get(strategy, strategy)}") + UniversalMessageDialog.show_info(self, "提示", f"已设置VR姿态策略为:{strategy_names.get(strategy, strategy)}", + False, "确定") else: - QMessageBox.warning(self, "错误", f"无效的姿态策略:{strategy}") + UniversalMessageDialog.show_warning(self, "错误", "设置VR姿态策略失败!", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"设置VR姿态策略时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"设置VR姿态策略时发生错误:\n{str(e)}", + False, "确定") def onTestVRPipeline(self): """测试VR管线监控功能""" try: if hasattr(self.world, 'vr_manager') and self.world.vr_manager: self.world.vr_manager.test_pipeline_monitoring() - QMessageBox.information(self, "VR管线测试", "管线监控测试已完成,请查看控制台输出。") + UniversalMessageDialog.show_info(self, "提示", "VR管线监控测试已开始,请稍等...", + False, "确定") else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"测试VR管线监控时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"测试VR管线监控时发生错误:\n{str(e)}", + False, "确定") def onShowVRDebugSettings(self): """显示VR调试设置对话框""" @@ -5520,68 +5728,184 @@ class MainWindow(QMainWindow): dialog = self.createVRDebugSettingsDialog() dialog.exec_() else: - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"打开VR调试设置时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"打开VR调试设置时发生错误:\n{str(e)}", + False, "确定") def createVRDebugSettingsDialog(self): - """创建VR调试设置对话框""" + """创建VR调试设置对话框(统一为 NewProjectDialog 风格)""" from PyQt5.QtWidgets import QCheckBox, QSlider from PyQt5.QtCore import Qt dialog = QDialog(self) dialog.setWindowTitle("VR调试设置") dialog.setModal(True) - dialog.resize(450, 400) + dialog.resize(508, 460) + dialog.setObjectName("newProjectDialog") + dialog.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint) + dialog.setAttribute(Qt.WA_TranslucentBackground, True) - layout = QVBoxLayout(dialog) + dialog.setStyleSheet(""" + QDialog#newProjectDialog { background-color: transparent; color: #EBEBEB; border: none; } + QFrame#baseFrame { background-color: #000000; border: 1px solid #3E3E42; border-radius: 5px; } + QWidget#titleBar { background-color: transparent; border: none; border-radius: 5px 5px 0 0; min-height: 32px; max-height: 32px; } + QWidget#titleBar QWidget { background-color: transparent; border: none; } + QLabel#titleLabel { color: #FFFFFF; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 14px; font-weight: 500; letter-spacing: 0.7px; } + QWidget#controlButtons QPushButton { background-color: transparent; border: none; color: #EBEBEB; font-size: 14px; min-width: 18px; max-width: 18px; min-height: 18px; max-height: 18px; padding: 0px; border-radius: 3px; } + QWidget#controlButtons QPushButton:hover { background-color: #2A2D2E; color: #FFFFFF; } + QPushButton#closeButton { border-radius: 0px 5px 0px 0px; } + QPushButton#closeButton:hover { background-color: #2A2D2E; color: #FFFFFF; } + QWidget#contentWidget { background-color: transparent; border-radius: 0 0 5px 5px; } + QFrame#contentContainer { background-color: #19191B; border: 1px solid #2C2F36; border-radius: 5px; } + QLabel[role="sectionTitle"] { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 12px; font-weight: 500; letter-spacing: 0.6px; } + QLabel[role="fieldLabel"] { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 12px; font-weight: 400; letter-spacing: 0.6px; } + QLabel { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; letter-spacing: 0.55px; } + QComboBox, QSpinBox, QDoubleSpinBox { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; } + QCheckBox { color: #EBEBEB; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; } + QLineEdit { background-color: rgba(89,100,113,0.2); color: #EBEBEB; border: 1px solid rgba(76,92,110,0.6); border-radius: 2px; padding: 6px 10px; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-size: 11px; font-weight: 300; letter-spacing: 0.55px; min-height: 14px; max-height: 30px; } + QLineEdit:focus { border: 1px solid #3067C0; background-color: rgba(48,103,192,0.1); } + QLineEdit:hover { border: 1px solid #3067C0; background-color: rgba(89,100,113,0.3); } + QLineEdit:disabled { background-color: rgba(89,100,113,0.1); color: rgba(235,235,235,0.4); border: 1px solid rgba(76,92,110,0.2); } + QPushButton { background-color: rgba(89,98,118,0.5); color: #EBEBEB; border: none; border-radius: 2px; padding: 0px 0px; font-family: 'Inter', 'Microsoft YaHei', sans-serif; font-weight: 300; font-size: 10px; letter-spacing: 0.5px; min-width: 90px; min-height: 30px; max-height: 30px; } + QPushButton:hover { background-color: #3067C0; color: #FFFFFF; } + QPushButton:pressed { background-color: #2556A0; color: #FFFFFF; } + QPushButton:disabled { background-color: rgba(89,98,118,0.3); color: rgba(235,235,235,0.4); } + QPushButton#primaryButton { background-color: rgba(89,98,118,0.5); border: none; color: #EBEBEB; font-weight: 300; min-width: 120px; max-width: 120px; } + QPushButton#primaryButton:hover { background-color: #2556A0; } + QPushButton#primaryButton:pressed { background-color: #1E4A8C; } + """) + + main_layout = QVBoxLayout(dialog) + main_layout.setContentsMargins(0,0,0,0) + main_layout.setSpacing(0) + base_frame = QFrame() + base_frame.setObjectName('baseFrame') + base_frame.setFrameShape(QFrame.NoFrame) + base_frame.setAttribute(Qt.WA_StyledBackground, True) + base_layout = QVBoxLayout(base_frame) + base_layout.setContentsMargins(0,0,0,0) + base_layout.setSpacing(0) + + title_bar = QWidget() + title_bar.setObjectName('titleBar') + tb_layout = QHBoxLayout(title_bar) + tb_layout.setContentsMargins(8,0,8,0) + tb_layout.setSpacing(6) + control_buttons = QWidget() + control_buttons.setObjectName('controlButtons') + cb_layout = QHBoxLayout(control_buttons) + cb_layout.setContentsMargins(0,0,0,0) + cb_layout.setSpacing(0) + close_btn = QPushButton() + close_btn.setObjectName('closeButton') + try: + close_btn.setIcon(get_icon('close_icon', QSize(18, 18))) + close_btn.setIconSize(QSize(18, 18)) + except Exception: pass + close_btn.clicked.connect(dialog.reject) + cb_layout.addWidget(close_btn) + left_placeholder = QWidget() + left_placeholder.setFixedWidth(control_buttons.sizeHint().width()) + tb_layout.addWidget(left_placeholder) + title_label = QLabel("VR调试设置") + title_label.setObjectName('titleLabel') + title_label.setAlignment(Qt.AlignCenter) + tb_layout.addWidget(title_label,1) + tb_layout.addWidget(control_buttons) + base_layout.addWidget(title_bar) + + dragging_state={'dragging':False,'pos':QPoint()} + def _tb_press(e): + if e.button()==Qt.LeftButton: dragging_state['dragging']=True; dragging_state['pos']=e.globalPos()-dialog.frameGeometry().topLeft(); e.accept() + else: e.ignore() + def _tb_move(e): + if e.buttons() & Qt.LeftButton and dragging_state['dragging']: dialog.move(e.globalPos()-dragging_state['pos']); e.accept() + else: e.ignore() + def _tb_release(e): + if e.button()==Qt.LeftButton: dragging_state['dragging']=False; e.accept() + else: e.ignore() + title_bar.mousePressEvent=_tb_press; title_bar.mouseMoveEvent=_tb_move; title_bar.mouseReleaseEvent=_tb_release + + content_widget = QWidget() + content_widget.setObjectName('contentWidget') + content_layout = QVBoxLayout(content_widget) + content_layout.setContentsMargins(10,10,10,10) + content_layout.setSpacing(0) + content_container = QFrame() + content_container.setObjectName('contentContainer') + content_container.setFrameShape(QFrame.NoFrame) + content_container.setAttribute(Qt.WA_StyledBackground, True) + container_layout = QVBoxLayout(content_container) + container_layout.setContentsMargins(15,10,15,10) + container_layout.setSpacing(10) # 获取当前设置 vr_manager = self.world.vr_manager debug_status = vr_manager.get_debug_status() perf_config = vr_manager.get_performance_monitoring_config() - # 调试状态显示 - status_group = QGroupBox("调试状态") - status_layout = QVBoxLayout() + # 左侧对齐辅助:统一字段列宽,并让小标题与控件左侧对齐 + label_column_width = 110 + def add_section_title(text): + title = QLabel(text) + title.setProperty('role','sectionTitle') + container_layout.addWidget(title) + + # 调试状态 + add_section_title("调试状态") + status_widget = QWidget() + status_layout = QVBoxLayout(status_widget) + status_layout.setContentsMargins(0,0,0,0) + status_layout.setSpacing(6) debug_enabled_label = QLabel(f"调试输出: {'启用' if debug_status['debug_enabled'] else '禁用'}") - debug_enabled_label.setStyleSheet(f"color: {'green' if debug_status['debug_enabled'] else 'red'};") + debug_enabled_label.setStyleSheet(f"color: {'#2dffc4' if debug_status['debug_enabled'] else 'red'};") status_layout.addWidget(debug_enabled_label) - debug_mode_label = QLabel(f"调试模式: {debug_status['debug_mode']}") status_layout.addWidget(debug_mode_label) - performance_label = QLabel(f"性能监控: {'启用' if debug_status['performance_monitoring'] else '禁用'}") - performance_label.setStyleSheet(f"color: {'green' if debug_status['performance_monitoring'] else 'red'};") + performance_label.setStyleSheet(f"color: {'#2dffc4' if debug_status['performance_monitoring'] else 'red'};") status_layout.addWidget(performance_label) - - status_group.setLayout(status_layout) - layout.addWidget(status_group) + container_layout.addWidget(status_widget) # 报告设置 - report_group = QGroupBox("报告设置") - report_layout = QFormLayout() - - # 报告间隔滑块 (5-120秒) + add_section_title("报告设置") + row_interval = QWidget() + row_interval_layout = QHBoxLayout(row_interval) + row_interval_layout.setContentsMargins(0,0,0,0) + row_interval_layout.setSpacing(10) + interval_text_label = QLabel("报告间隔:") + interval_text_label.setProperty('role','fieldLabel') + interval_text_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_interval_layout.addWidget(interval_text_label) interval_slider = QSlider(Qt.Horizontal) interval_slider.setMinimum(5) interval_slider.setMaximum(120) interval_slider.setValue(int(debug_status['report_interval_seconds'])) interval_slider.setTickPosition(QSlider.TicksBelow) interval_slider.setTickInterval(15) - interval_label = QLabel(f"{int(debug_status['report_interval_seconds'])}秒") interval_slider.valueChanged.connect(lambda v: interval_label.setText(f"{v}秒")) + inner = QHBoxLayout() + inner.setContentsMargins(0,0,0,0) + inner.setSpacing(6) + inner.addWidget(interval_slider) + inner.addWidget(interval_label) + row_interval_layout.addLayout(inner,1) + container_layout.addWidget(row_interval) - interval_layout = QHBoxLayout() - interval_layout.addWidget(interval_slider) - interval_layout.addWidget(interval_label) - report_layout.addRow("报告间隔:", interval_layout) - - # 性能检查间隔 + row_check = QWidget() + row_check_layout = QHBoxLayout(row_check) + row_check_layout.setContentsMargins(0,0,0,0) + row_check_layout.setSpacing(10) + check_label = QLabel("性能检查间隔:") + check_label.setProperty('role','fieldLabel') + check_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_check_layout.addWidget(check_label) check_interval_combo = QComboBox() - check_interval_combo.addItems(["0.1秒", "0.5秒", "1.0秒", "2.0秒"]) + check_interval_combo.addItems(["0.1秒","0.5秒","1.0秒","2.0秒"]) current_check_interval = perf_config['check_interval'] if current_check_interval == 0.1: check_interval_combo.setCurrentIndex(0) @@ -5591,93 +5915,92 @@ class MainWindow(QMainWindow): check_interval_combo.setCurrentIndex(2) else: check_interval_combo.setCurrentIndex(3) - report_layout.addRow("性能检查间隔:", check_interval_combo) + row_check_layout.addWidget(check_interval_combo,1) + container_layout.addWidget(row_check) - # 帧历史大小 + row_hist = QWidget(); row_hist_layout = QHBoxLayout(row_hist) + row_hist_layout.setContentsMargins(0,0,0,0) + row_hist_layout.setSpacing(10) + hist_label = QLabel("帧时间历史:") + hist_label.setProperty('role','fieldLabel') + hist_label.setAlignment(Qt.AlignRight|Qt.AlignVCenter) + row_hist_layout.addWidget(hist_label) frame_history_spin = QSpinBox() frame_history_spin.setMinimum(10) frame_history_spin.setMaximum(1000) frame_history_spin.setValue(perf_config['frame_history_size']) frame_history_spin.setSuffix(" 帧") - report_layout.addRow("帧时间历史:", frame_history_spin) - - report_group.setLayout(report_layout) - layout.addWidget(report_group) + row_hist_layout.addWidget(frame_history_spin,1) + container_layout.addWidget(row_hist) # 监控项目 - monitor_group = QGroupBox("监控项目") - monitor_layout = QVBoxLayout() - + add_section_title("监控项目") + monitor_widget = QWidget() + monitor_layout = QVBoxLayout(monitor_widget) + monitor_layout.setContentsMargins(0,0,0,0) + monitor_layout.setSpacing(6) cpu_check = QCheckBox("CPU使用率") cpu_check.setChecked(perf_config['psutil_available']) cpu_check.setEnabled(perf_config['psutil_available']) monitor_layout.addWidget(cpu_check) - memory_check = QCheckBox("内存使用率") memory_check.setChecked(perf_config['psutil_available']) memory_check.setEnabled(perf_config['psutil_available']) monitor_layout.addWidget(memory_check) - gpu_check = QCheckBox("GPU使用率") gpu_check.setChecked(perf_config['gputil_available'] or perf_config['nvidia_ml_available']) gpu_check.setEnabled(perf_config['gputil_available'] or perf_config['nvidia_ml_available']) monitor_layout.addWidget(gpu_check) - frame_time_check = QCheckBox("帧时间统计") frame_time_check.setChecked(True) monitor_layout.addWidget(frame_time_check) + container_layout.addWidget(monitor_widget) - monitor_group.setLayout(monitor_layout) - layout.addWidget(monitor_group) - - # 按钮 + separator_buttons = QFrame() + separator_buttons.setFrameShape(QFrame.HLine) + separator_buttons.setFrameShadow(QFrame.Plain) + separator_buttons.setFixedHeight(1) + separator_buttons.setStyleSheet("background-color: #2C2F36; border: none;") + container_layout.addWidget(separator_buttons) button_layout = QHBoxLayout() - apply_button = QPushButton("应用") reset_button = QPushButton("重置计数器") ok_button = QPushButton("确定") + # ok_button.setObjectName("primaryButton") cancel_button = QPushButton("取消") - button_layout.addWidget(apply_button) button_layout.addWidget(reset_button) button_layout.addStretch() button_layout.addWidget(ok_button) button_layout.addWidget(cancel_button) + container_layout.addLayout(button_layout) - layout.addLayout(button_layout) + content_layout.addWidget(content_container, 0, Qt.AlignTop) + base_layout.addWidget(content_widget); main_layout.addWidget(base_frame) - # 连接信号 def apply_settings(): try: - # 应用报告间隔 new_interval_seconds = interval_slider.value() - new_interval_frames = int(new_interval_seconds * 60) # 假设60fps + new_interval_frames = int(new_interval_seconds * 60) vr_manager.set_performance_report_interval(new_interval_frames) - - # 应用性能检查间隔 check_intervals = [0.1, 0.5, 1.0, 2.0] new_check_interval = check_intervals[check_interval_combo.currentIndex()] vr_manager.set_performance_check_interval(new_check_interval) - - # 应用帧历史大小 vr_manager.set_frame_time_history_size(frame_history_spin.value()) - - QMessageBox.information(dialog, "成功", "VR调试设置已应用!") + UniversalMessageDialog.show_success(dialog, "成功", "VR调试设置已应用!", False, "确定") except Exception as e: - QMessageBox.critical(dialog, "错误", f"应用设置时发生错误:\n{str(e)}") - + UniversalMessageDialog.show_error(dialog, "错误", f"应用设置时发生错误:\n{str(e)}", False, "确定") def reset_counters(): try: vr_manager.reset_performance_counters() - QMessageBox.information(dialog, "成功", "性能计数器已重置!") + UniversalMessageDialog.show_success(dialog, "成功", "性能计数器已重置!", False, "确定") except Exception as e: - QMessageBox.critical(dialog, "错误", f"重置计数器时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(dialog, "错误", f"重置计数器时发生错误:\n{str(e)}", False, "确定") apply_button.clicked.connect(apply_settings) reset_button.clicked.connect(reset_counters) ok_button.clicked.connect(lambda: (apply_settings(), dialog.accept())) cancel_button.clicked.connect(dialog.reject) - return dialog # ==================== VR测试模式事件处理 ==================== @@ -5690,26 +6013,31 @@ class MainWindow(QMainWindow): # 启用VR测试模式 success = self.world.vr_manager.enable_vr_test_mode(display_mode='stereo') if success: - QMessageBox.information(self, "VR测试模式", - "VR测试模式已启用!\n\n现在VR渲染内容将直接显示在PC屏幕上,无需VR头显。\n\n特点:\n- 显示VR左右眼视图\n- 实时性能监控HUD\n- 复用完整VR渲染管线\n- 可测量纯渲染性能") + UniversalMessageDialog.show_info(self, "VR测试模式", + "VR测试模式已启用!\n\n现在VR渲染内容将直接显示在PC屏幕上,无需VR头显。\n\n特点:\n- 显示VR左右眼视图\n- 实时性能监控HUD\n- 复用完整VR渲染管线\n- 可测量纯渲染性能", + False, "确定") print("✅ VR测试模式已启用") # 可选:自动开启性能测试 self.world.vr_manager.run_vr_performance_test(duration_seconds=10) else: self.vrTestModeAction.setChecked(False) - QMessageBox.warning(self, "错误", "启用VR测试模式失败!") + UniversalMessageDialog.show_warning(self, "错误", "启用VR测试模式失败!", + False, "确定") else: # 禁用VR测试模式 self.world.vr_manager.disable_vr_test_mode() - QMessageBox.information(self, "VR测试模式", "VR测试模式已禁用") + UniversalMessageDialog.show_info(self, "VR测试模式", "VR测试模式已禁用!", + False, "确定") print("✅ VR测试模式已禁用") else: self.vrTestModeAction.setChecked(False) - QMessageBox.warning(self, "错误", "VR管理器不可用!") + UniversalMessageDialog.show_warning(self, "错误", "VR管理器不可用!", + False, "确定") except Exception as e: self.vrTestModeAction.setChecked(False) - QMessageBox.critical(self, "错误", f"切换VR测试模式时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"切换VR测试模式时发生错误:\n{str(e)}", + False, "确定") def onToggleVRTestSubmitTexture(self): """切换VR测试模式纹理提交功能""" @@ -5718,7 +6046,8 @@ class MainWindow(QMainWindow): enabled = self.vrTestSubmitTextureAction.isChecked() self.world.vr_manager.set_test_mode_features(submit_texture=enabled) except Exception as e: - QMessageBox.critical(self, "错误", f"设置纹理提交功能时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"设置纹理提交功能时发生错误:\n{str(e)}", + False, "确定") def onToggleVRTestWaitPoses(self): """切换VR测试模式姿态等待功能""" @@ -5727,7 +6056,8 @@ class MainWindow(QMainWindow): enabled = self.vrTestWaitPosesAction.isChecked() self.world.vr_manager.set_test_mode_features(wait_poses=enabled) except Exception as e: - QMessageBox.critical(self, "错误", f"设置姿态等待功能时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"设置姿态等待功能时发生错误:\n{str(e)}", + False, "确定") def onSetVRTestStep(self, step): """设置VR测试步骤""" @@ -5737,24 +6067,29 @@ class MainWindow(QMainWindow): self.world.vr_manager.set_test_mode_features(submit_texture=False, wait_poses=False) self.vrTestSubmitTextureAction.setChecked(False) self.vrTestWaitPosesAction.setChecked(False) - QMessageBox.information(self, "VR测试", "已重置为基线状态:两个功能都禁用") + UniversalMessageDialog.show_info(self, "VR测试", "已重置为基线状态:两个功能都禁用", + False, "确定") elif step == 1: # 只启用纹理提交 self.world.vr_manager.set_test_mode_features(submit_texture=True, wait_poses=False) self.vrTestSubmitTextureAction.setChecked(True) self.vrTestWaitPosesAction.setChecked(False) - QMessageBox.information(self, "VR测试", "步骤1:只启用纹理提交\n观察FPS变化来判断submit_texture是否影响性能") + UniversalMessageDialog.show_info(self, "VR测试", "步骤1:只启用纹理提交\n观察FPS变化来判断submit_texture是否影响性能", + False, "确定") elif step == 2: # 只启用姿态等待 self.world.vr_manager.set_test_mode_features(submit_texture=False, wait_poses=True) self.vrTestSubmitTextureAction.setChecked(False) self.vrTestWaitPosesAction.setChecked(True) - QMessageBox.information(self, "VR测试", "步骤2:只启用姿态等待\n观察FPS变化来判断waitGetPoses是否影响性能") + UniversalMessageDialog.show_info(self, "VR测试", "步骤2:只启用姿态等待\n观察FPS变化来判断waitGetPoses是否影响性能", + False, "确定") elif step == 3: # 同时启用两者 self.world.vr_manager.set_test_mode_features(submit_texture=True, wait_poses=True) self.vrTestSubmitTextureAction.setChecked(True) self.vrTestWaitPosesAction.setChecked(True) - QMessageBox.information(self, "VR测试", "步骤3:同时启用两者\n这应该完全复现普通VR模式的36FPS问题") + UniversalMessageDialog.show_info(self, "VR测试", "步骤3:同时启用两者\n这应该完全复现普通VR模式的36FPS问题", + False, "确定") except Exception as e: - QMessageBox.critical(self, "错误", f"设置VR测试步骤时发生错误:\n{str(e)}") + UniversalMessageDialog.show_error(self, "错误", f"设置VR测试步骤时发生错误:\n{str(e)}", + False, "确定") def setup_main_window(world,path = None): """设置主窗口的便利函数"""