Files
Feeding_control_system/controller/bottom_control_controller.py

251 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# controller/bottom_control_controller.py
from PySide6.QtCore import Qt, QPropertyAnimation, QRect, QParallelAnimationGroup, QEasingCurve, QPoint, Slot
from view.widgets.system_center_dialog import SystemCenterDialog
from view.widgets.bottom_control_widget import BottomControlWidget
from view.widgets.system_diagnostics_dialog import SystemDiagnosticsDialog
from view.widgets.message_popup_widget import MessagePopupWidget
from service.msg_recorder import MessageRecorder
from service.msg_query_thread import MsgQueryThread
"""
控制主界面底部的所有按钮, 包括系统诊断、系统中心等的行为。
以及 版本信息相关弹窗, 如: v1.0
"""
class BottomControlController:
def __init__(self, bottom_control_widget:BottomControlWidget, main_window):
self.bottom_control_widget = bottom_control_widget
self.main_window = main_window
# 系统诊断弹窗
self.system_diagnostics_dialog = SystemDiagnosticsDialog(self.main_window)
self._init_system_diagnostics_dialog_hide_animations()
# 系统中心弹窗
self.system_center_dialog = SystemCenterDialog(self.main_window)
self._init_system_center_dialog_hide_animations()
# ===================== 消息列表相关 ====================================
# 系统状态消息列表控件
self.status_msg_widget = MessagePopupWidget("系统状态消息", self.main_window)
# 预警消息列表控件
self.warning_msg_widget = MessagePopupWidget("预警消息", self.main_window)
# 消息数据库查询线程
self.msg_query_thread = MsgQueryThread() # 默认1秒查询一次每次16条消息
# 连接线程信号到UI更新函数
self.msg_query_thread.new_messages.connect(self.update_message_ui, Qt.QueuedConnection)
self.msg_query_thread.start() # 启动线程
# =======================================================================
# 绑定主界面底部按钮的信号(如:系统诊断按钮等,点击触发弹窗)
self._bind_buttons()
# 绑定弹窗中按钮的信号
self._bind_dialog_signals()
@Slot(int, list)
def update_message_ui(self, message_type, messages):
"""根据消息类型更新对应UI, message_type为1表示系统状态消息, 为2表示预警消息"""
# 清空当前消息列表(避免重复)
target_widget = self.status_msg_widget if message_type == 1 else self.warning_msg_widget
target_widget.list_widget.clear()
# target_widget.messages.clear()
# 添加新消息 (第三个为 create_time, 第四个为 last_modified)
for content, is_processed, create_time, _ in messages:
# 从create_time中提取时分秒
# time_part = create_time.split()[1] # 空格分隔之后的[1]为时分秒
# 需要添加到消息列表的消息格式为 时分秒 + 消息原始内容
# msg_list_content = f"{create_time} {content}"
target_widget.add_message(content, is_processed = bool(is_processed), msg_time = create_time)
def stop_threads(self):
"""停止当前控制器中的所有线程"""
if hasattr(self, 'msg_query_thread') and self.msg_query_thread.isRunning():
self.msg_query_thread.stop()
def _bind_buttons(self):
# 底部系统中心按钮 → 触发弹窗显示/隐藏
self.bottom_control_widget.center_btn.clicked.connect(self.toggle_system_center_dialog)
# 底部系统诊断按钮 → 触发弹窗显示/隐藏
self.bottom_control_widget.diagnosis_btn.clicked.connect(self.toggle_system_diagnostics_dialog)
# 底部系统状态消息按钮 → 触发系统状态消息列表显示/隐藏
self.bottom_control_widget.status_msg_btn.clicked.connect(self.toggle_system_status_msg_list)
# 底部预警消息列表按钮 → 触发预警消息列表显示/隐藏
self.bottom_control_widget.warning_list_btn.clicked.connect(self.toggle_system_warning_msg_list)
def _bind_dialog_signals(self):
"""绑定弹窗按钮的信号"""
# 系统中心弹窗的按钮信号
self.system_center_dialog.sys_setting_clicked.connect(self.handle_sys_setting)
self.system_center_dialog.data_center_clicked.connect(self.handle_data_center)
self.system_center_dialog.user_center_clicked.connect(self.handle_user_center)
def _init_system_center_dialog_hide_animations(self):
"""初始化系统中心弹窗隐藏动画(淡出+缩小,与显示动画对应)"""
# 1. 淡出动画
self.hide_opacity_anim = QPropertyAnimation(self.system_center_dialog, b"windowOpacity", self.system_center_dialog)
self.hide_opacity_anim.setDuration(200)
self.hide_opacity_anim.setStartValue(1.0)
self.hide_opacity_anim.setEndValue(0.0)
# 2. 缩小动画
self.hide_scale_anim = QPropertyAnimation(self.system_center_dialog, b"geometry", self.system_center_dialog)
self.hide_scale_anim.setDuration(200)
self.hide_scale_anim.setEasingCurve(QEasingCurve.InBack) # 收缩感
# 3. 组合动画(父对象设为弹窗)
self.hide_anim_group = QParallelAnimationGroup(self.system_center_dialog)
self.hide_anim_group.addAnimation(self.hide_opacity_anim)
self.hide_anim_group.addAnimation(self.hide_scale_anim)
# 动画结束后,强制隐藏弹窗
self.hide_anim_group.finished.connect(self.system_center_dialog.hide)
def toggle_system_center_dialog(self):
"""切换系统中心弹窗的显示/隐藏状态"""
if self.system_center_dialog.isVisible():
# 已显示 → 隐藏
# self.system_center_dialog.hide()
# 动态设置缩小动画的起点和终点(基于当前弹窗位置)
current_geo = self.system_center_dialog.geometry()
end_rect = QRect(
current_geo.center().x() - current_geo.width() * 0.4,
current_geo.center().y() - current_geo.height() * 0.4,
int(current_geo.width() * 0.8),
int(current_geo.height() * 0.8)
)
self.hide_scale_anim.setStartValue(current_geo)
self.hide_scale_anim.setEndValue(end_rect)
# 启动隐藏动画 (隐藏动画结束,自动隐藏 系统中心弹窗)
self.hide_anim_group.start()
else:
# 未显示 → 计算位置并显示
self._calc_system_center_dialog_position() # 每次显示都计算位置
self.system_center_dialog.show()
def _calc_system_center_dialog_position(self):
"""计算系统中心弹窗位置, 并move移动"""
btn = self.bottom_control_widget.center_btn
bottom_widget = self.bottom_control_widget
# 计算按钮相对于主窗口的位置
bottom_pos_rel_main = bottom_widget.pos()
btn_pos_rel_bottom = btn.pos()
btn_pos_rel_main = bottom_pos_rel_main + btn_pos_rel_bottom
# 计算弹窗坐标
btn_width = btn.width()
dialog_size = self.system_center_dialog.size()
dialog_x = btn_pos_rel_main.x() + (btn_width - dialog_size.width()) // 2
dialog_y = btn_pos_rel_main.y() - dialog_size.height()
# 设置弹窗位置
self.system_center_dialog.move(dialog_x, dialog_y)
# ------------------- 系统中心弹窗业务逻辑-------------------
def handle_sys_setting(self):
"""系统设置按钮的业务逻辑"""
# print("执行系统设置逻辑:如打开系统配置窗口、修改参数等")
# 示例:打开系统配置弹窗(后续可新建 SystemSettingDialog
# setting_dialog = SystemSettingDialog(self.main_window)
# setting_dialog.exec()
def handle_data_center(self):
"""数据中心按钮的业务逻辑"""
# print("执行数据中心逻辑:如查看生产数据、导出报表等")
def handle_user_center(self):
"""用户中心按钮的业务逻辑"""
# print("执行用户中心逻辑:如切换用户、修改密码等")
# ------------------- 系统诊断弹窗逻辑-------------------
def _init_system_diagnostics_dialog_hide_animations(self):
"""初始化系统诊断弹窗隐藏动画(与显示动画反向:滑出+淡出)"""
# 1. 淡出动画(与显示动画时长一致)
self.dia_hide_opacity_anim = QPropertyAnimation(
self.system_diagnostics_dialog, b"windowOpacity", self.system_diagnostics_dialog
)
self.dia_hide_opacity_anim.setDuration(300) # 显示动画为400ms
self.dia_hide_opacity_anim.setStartValue(1.0)
self.dia_hide_opacity_anim.setEndValue(0.0)
# 2. 位置动画从当前位置滑出到下方100px与显示动画反向
self.dia_hide_pos_anim = QPropertyAnimation(
self.system_diagnostics_dialog, b"geometry", self.system_diagnostics_dialog
)
self.dia_hide_pos_anim.setDuration(300)
self.dia_hide_pos_anim.setEasingCurve(QEasingCurve.InQuart) # 滑出曲线与显示反向
# 3. 组合动画(同时执行滑出和淡出)
self.dia_hide_anim_group = QParallelAnimationGroup(self.system_diagnostics_dialog)
self.dia_hide_anim_group.addAnimation(self.dia_hide_opacity_anim)
self.dia_hide_anim_group.addAnimation(self.dia_hide_pos_anim)
# 动画结束后强制隐藏弹窗
self.dia_hide_anim_group.finished.connect(self.system_diagnostics_dialog.hide)
def toggle_system_diagnostics_dialog(self):
"""切换系统诊断弹窗的显示/隐藏状态"""
if self.system_diagnostics_dialog.isVisible():
# 已显示 → 执行隐藏动画
self._start_diagnostics_hide_animation()
else:
# 未显示 → 计算位置并显示(触发显示动画)
self._calc_system_diagnostics_dialog_position()
self.system_diagnostics_dialog.show()
def _calc_system_diagnostics_dialog_position(self):
"""计算系统诊断弹窗位置(显示在系统诊断按钮上方)"""
btn = self.bottom_control_widget.diagnosis_btn # 诊断按钮
btn_pos = btn.mapToGlobal(QPoint(0, 0))
dialog_x = btn_pos.x()
dialog_y = btn_pos.y() - self.system_diagnostics_dialog.height()
# 设置弹窗位置(动画会基于此位置执行滑入效果)
self.system_diagnostics_dialog.move(dialog_x, dialog_y)
def _start_diagnostics_hide_animation(self):
"""启动系统诊断弹窗的隐藏动画(滑出+淡出)"""
current_geo = self.system_diagnostics_dialog.geometry() # 当前位置和尺寸
# 计算隐藏动画终点当前位置下方100px与显示动画起点对应
end_rect = QRect(
current_geo.x(),
current_geo.y() + 100, # 向下滑出100px
current_geo.width(),
current_geo.height()
)
# 设置动画参数并启动
self.dia_hide_pos_anim.setStartValue(current_geo)
self.dia_hide_pos_anim.setEndValue(end_rect)
self.dia_hide_anim_group.start()
# ================== 系统状态消息列表: 显示系统消息 ===================
def toggle_system_status_msg_list(self):
"""系统状态消息按钮点击之后 显示系统消息"""
if not self.status_msg_widget.isVisible():
btn_pos = self.bottom_control_widget.status_msg_btn.mapToGlobal(QPoint(0, 0))
popup_x = btn_pos.x()
popup_y = btn_pos.y() - self.status_msg_widget.height()
self.status_msg_widget.move(popup_x, popup_y)
self.status_msg_widget.show()
else:
self.status_msg_widget.close()
# ================== 预警消息列表: 显示预警消息 ===================
def toggle_system_warning_msg_list(self):
"""预警消息列表按钮点击之后 显示预警消息"""
if not self.warning_msg_widget.isVisible():
btn_pos = self.bottom_control_widget.warning_list_btn.mapToGlobal(QPoint(0, 0))
popup_x = btn_pos.x()
popup_y = btn_pos.y() - self.warning_msg_widget.height()
self.warning_msg_widget.move(popup_x, popup_y)
self.warning_msg_widget.show()
else:
self.warning_msg_widget.close()