You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
593 lines
23 KiB
593 lines
23 KiB
# main.py
|
|
import sys
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenu, QAction,QActionGroup,
|
|
QWidget, QGridLayout, QLabel, QRubberBand)
|
|
from PyQt5.QtCore import QObject, Qt, pyqtSignal, QPoint, QRect, QSize
|
|
from PyQt5.QtGui import QMouseEvent, QCursor
|
|
from core.preset_manager import PresetManager
|
|
from panel.preset_panel import PresetPanel
|
|
|
|
from panel.log_panel import LogPanel
|
|
# 如果你上面用了纯Python写法没用PyQt信号,这里还需要:
|
|
from utils.logger import logger
|
|
from core.serial_protocol import SerialProtocol
|
|
|
|
|
|
from panel.connection_panel import ConnectionPanel
|
|
from utils.globals import get_serial_manager
|
|
|
|
# 导入 UI
|
|
from ui.ui_main import Ui_MainWindow
|
|
# 导入核心控制器(假设你已经写好了)
|
|
from core.device_manager import MatrixController
|
|
|
|
|
|
class ScreenLabel(QLabel):
|
|
|
|
split_solution = []
|
|
click_labels = []
|
|
|
|
"""自定义 Label,增加了右键信号"""
|
|
# 定义一个右键信号,携带当前屏幕的 ID
|
|
rightClicked = pyqtSignal(int)
|
|
|
|
def __init__(self, screen_id, text=""):
|
|
super().__init__(text)
|
|
self.screen_id = screen_id
|
|
self.is_selected = False
|
|
self.init_style()
|
|
|
|
def init_style(self):
|
|
"""初始化样式:灰色背景"""
|
|
self.setAlignment(Qt.AlignCenter)
|
|
self.setStyleSheet("""
|
|
background-color: rgb(85, 85, 85);
|
|
color: white;
|
|
border: 1px solid rgb(50, 50, 50);
|
|
font-weight: bold;
|
|
""")
|
|
|
|
def mousePressEvent(self, event: QMouseEvent):
|
|
"""
|
|
设置鼠标点击动作
|
|
"""
|
|
if event.button() == Qt.RightButton:
|
|
# 发射右键信号
|
|
self.rightClicked.emit(self.screen_id)
|
|
|
|
# if event.button() == Qt.LeftButton:
|
|
# if ScreenLabel.split_solution[self.screen_id - 1]['status'] < 2:
|
|
# # 切换选中状态
|
|
# self.is_selected = not self.is_selected
|
|
# self.update_style()
|
|
#
|
|
# # 这里可以 emit 一个信号告诉主窗口
|
|
# elif event.button() == Qt.RightButton:
|
|
# # 发射右键信号
|
|
# self.rightClicked.emit(self.screen_id)
|
|
|
|
def set_selected(self, selected):
|
|
"""
|
|
设置屏幕控件的选中状态
|
|
:param selected: bool, True为选中(高亮),False为取消选中(正常)
|
|
"""
|
|
self.is_selected = selected # 保存状态
|
|
self.update_style()
|
|
|
|
# if selected:
|
|
# # 如果选中,设置一个红色/蓝色的边框,或者背景色
|
|
# self.setStyleSheet("""
|
|
# border: 2px solid red;
|
|
# background-color: rgba(255, 0, 0, 0.1);
|
|
# """)
|
|
# else:
|
|
# # 如果取消选中,恢复默认样式(假设默认是灰色边框)
|
|
# self.setStyleSheet("""
|
|
# border: 1px solid gray;
|
|
# background-color: white;
|
|
# """)
|
|
|
|
# 强制刷新界面
|
|
self.update()
|
|
|
|
def update_style(self):
|
|
if self.is_selected:
|
|
|
|
if self.screen_id not in ScreenLabel.click_labels:
|
|
ScreenLabel.click_labels.append(self.screen_id)
|
|
|
|
ScreenLabel.split_solution[self.screen_id - 1]['status'] = 1
|
|
# 选中状态:蓝色背景
|
|
self.setStyleSheet("""
|
|
background-color: rgb(0, 170, 255);
|
|
color: white;
|
|
border: 2px solid yellow;
|
|
font-weight: bold;
|
|
""")
|
|
else:
|
|
if self.screen_id in ScreenLabel.click_labels:
|
|
ScreenLabel.click_labels.remove(self.screen_id)
|
|
|
|
if ScreenLabel.split_solution[self.screen_id - 1]:
|
|
ScreenLabel.split_solution[self.screen_id - 1]['status'] = 0
|
|
|
|
self.init_style()
|
|
|
|
class MatrixControlApp(QMainWindow, Ui_MainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setupUi(self)
|
|
|
|
# --- 核心控制器 ---
|
|
self.matrix = MatrixController()
|
|
|
|
# --- 屏幕管理 ---
|
|
# 假设你在 Designer 里把 12 个 Label 的名字分别命名为 screen_1 到 screen_12
|
|
self.screen_labels = []
|
|
# --- 新增:初始化屏幕列表 ---
|
|
self.screen_widgets_list = []
|
|
self.init_screen_widgets()
|
|
|
|
self.serial_protocol = SerialProtocol()
|
|
|
|
# 1. 初始化预案管理器
|
|
self.preset_manager = PresetManager()
|
|
|
|
# 2. 初始化预案面板
|
|
self.preset_panel = PresetPanel(self.preset_manager, self)
|
|
|
|
# 3. 将面板添加到主窗口布局中
|
|
self.main_layout.addWidget(self.preset_panel)
|
|
|
|
# --- 新增:用于框选的变量 ---
|
|
self.rubber_band = QRubberBand(QRubberBand.Rectangle, self.widget_container)
|
|
self.rubber_band.setStyleSheet("border: 2px solid red; background-color: rgba(255, 0, 0, 50);")
|
|
self.origin = QPoint()
|
|
|
|
# --- 新增:连接容器的鼠标事件 ---
|
|
self.widget_container.mousePressEvent = self.mouse_press_event
|
|
self.widget_container.mouseMoveEvent = self.mouse_move_event
|
|
self.widget_container.mouseReleaseEvent = self.mouse_release_event
|
|
|
|
# --- 1. 初始化串口管理器 ---
|
|
# 注意:这里我们把串口管理器作为实例属性,方便全局调用
|
|
# from core.connection_manager import SerialManager
|
|
# self.serial_manager = SerialManager()
|
|
|
|
# --- 修改这里:获取全局实例,而不是自己 new ---
|
|
self.serial_manager = get_serial_manager()
|
|
|
|
# 初始化连接面板时,也传这个实例进去
|
|
self.conn_panel = ConnectionPanel(self.serial_manager)
|
|
|
|
# ... 初始化 screen_widgets_list 等逻辑 ...
|
|
|
|
# --- 2. 创建面板实例 ---
|
|
# self.conn_panel = ConnectionPanel()
|
|
|
|
# --- 3. 将面板加入布局 ---
|
|
# 建议放在 PresetPanel 上方
|
|
self.main_layout.addWidget(self.conn_panel) # 新增:连接面板
|
|
self.main_layout.addWidget(self.preset_panel)
|
|
|
|
# --- 集成日志面板 ---
|
|
self.log_panel = LogPanel()
|
|
|
|
# 假设你使用 QVBoxLayout 作为主布局
|
|
self.main_layout.addWidget(self.log_panel)
|
|
|
|
# --- 发送一条测试日志 ---
|
|
logger.info("矩阵控制软件启动成功!")
|
|
logger.debug("调试模式已开启")
|
|
|
|
self.show()
|
|
|
|
def init_screen_widgets(self):
|
|
"""初始化 12 个屏幕控件,替换为自定义的 ScreenLabel"""
|
|
grid_layout = self.gridLayout_screens # 假设你把 12 个 Label 放在一个名为 gridLayout_screens 的布局里
|
|
|
|
for i in range(1, 13): # 1 到 12
|
|
# 获取 Designer 中的占位 Label (或者你直接在 Designer 中提升为 ScreenLabel)
|
|
# 这里为了演示,我们直接创建新的
|
|
label = ScreenLabel(screen_id=i, text=f"Screen {i}\n(空闲)")
|
|
|
|
# 连接右键信号
|
|
label.rightClicked.connect(self.on_screen_right_clicked)
|
|
|
|
# 假设是 4列 x 3行 布局
|
|
row = (i - 1) // 4 # 0,0,0,0, 1,1,1,1, 2,2,2,2
|
|
col = (i - 1) % 4 # 0,1,2,3, 0,1,2,3, 0,1,2,3
|
|
grid_layout.addWidget(label, row, col)
|
|
|
|
self.screen_labels.append(label)
|
|
|
|
label_screen = {}
|
|
label_screen['screen_id'] = i
|
|
label_screen['status'] = 0 # 屏幕状态:0为空闲、1为已选中、2为已设定、3为已拼接
|
|
label_screen['source_type'] = 0
|
|
label_screen['source_id'] = 0
|
|
label_screen['big_pic_id'] = 0
|
|
|
|
# 保存分屏方案
|
|
ScreenLabel.split_solution.append(label_screen)
|
|
|
|
# 如果你在 Designer 里已经画好了 Label,可以用下面这种方法替换:
|
|
# self.ui.label_1.setParent(None)
|
|
# grid_layout.addWidget(ScreenLabel(1), 0, 0)
|
|
|
|
def on_screen_right_clicked(self, screen_id):
|
|
"""处理右键点击事件"""
|
|
print(f"屏幕 {screen_id} 被右键点击了")
|
|
|
|
if len(ScreenLabel.click_labels) > 1 and screen_id in ScreenLabel.click_labels:
|
|
"""处理拼接屏幕事件"""
|
|
# 1. 创建菜单
|
|
menu = QMenu(self)
|
|
menu.addAction(f"--- 屏幕 {screen_id} ---")
|
|
menu.addSeparator()
|
|
split_act = QAction("拼接屏幕", self)
|
|
menu.addAction(split_act)
|
|
|
|
action = menu.exec_(QCursor.pos())
|
|
if action == split_act:
|
|
self.set_split(screen_id)
|
|
else:
|
|
# 1. 创建菜单
|
|
menu = QMenu(self)
|
|
menu.addAction(f"--- 屏幕 {screen_id} ---")
|
|
menu.addSeparator()
|
|
|
|
# 2. 模拟信号源选项
|
|
source_group = QActionGroup(self) # 使用 QActionGroup 来实现单选
|
|
new_var_name = []
|
|
available_sources = [
|
|
{"type": 0x33, "id": 0x01, "name": "HDMI 1"},
|
|
{"type": 0x35, "id": 0x01, "name": "DVI 1"},
|
|
{"type": 0x32, "id": 0x01, "name": "AV 1"}, # SourceType=0x32, Sourceld=0x01
|
|
{"type": 0x32, "id": 0x02, "name": "AV 2"},
|
|
]
|
|
|
|
# 模拟信号源列表,实际可以从设备读取
|
|
# available_sources = ["HDMI 1", "HDMI 2", "DP 1", "DP 2", "Camera 1", "Test Pattern"]
|
|
for item in available_sources: # 这里用 enumerate 替代手动 k+=1
|
|
# 1. 创建 QAction 对象
|
|
action = QAction(item['name'], self)
|
|
action.setData(item)
|
|
|
|
# 2. 如果需要动态变量名存入全局(虽然不推荐,但如果你必须用)
|
|
new_var_name.append(action)
|
|
|
|
# 3. 将 QAction 对象添加到菜单 (关键修改在这里)
|
|
menu.addAction(action)
|
|
|
|
menu.addSeparator()
|
|
cancel_act = QAction("清除信号", self)
|
|
menu.addAction(cancel_act)
|
|
|
|
# 3. 显示菜单并获取结果
|
|
action = menu.exec_(QCursor.pos())
|
|
|
|
if action == cancel_act:
|
|
self.clear_screen(screen_id)
|
|
|
|
for k, item in enumerate(available_sources, start=0):
|
|
if action == new_var_name[k]:
|
|
self.assign_source_to_screen(screen_id, item)
|
|
|
|
def get_current_layout_params(self):
|
|
"""
|
|
获取当前的拼接布局参数。
|
|
这里是一个示例实现,你需要根据你之前的“框选逻辑”调整。
|
|
"""
|
|
# --- 方案 A:如果你在框选结束后,把参数存到了实例变量里(推荐)---
|
|
# 比如你在 mouse_release_event 里计算完后,执行了: self.current_mosaic_params = params
|
|
if hasattr(self, 'current_mosaic_params'):
|
|
return [self.current_mosaic_params] # 注意:通常返回一个列表,因为可能有多组拼接
|
|
else:
|
|
# 如果没有选中任何东西,返回一个默认值或空列表
|
|
print("Warning: 没有找到当前布局参数,返回默认单屏")
|
|
return [{
|
|
"start": 0,
|
|
"hcount": 1,
|
|
"vcount": 1
|
|
}]
|
|
|
|
# --- 方案 B:如果你需要实时遍历所有屏幕去计算(复杂,但数据最准)---
|
|
# 这部分逻辑比较重,通常我们用 方案 A 的缓存方式。
|
|
|
|
def assign_source_to_screen(self, screen_id, source):
|
|
"""分配信号源给屏幕"""
|
|
|
|
# 2. 【新增】通过串口管理器发送
|
|
# 这里的 self.serial_manager 来自于我们在 main.py 中的初始化
|
|
if hasattr(self, 'serial_manager') and self.serial_manager.is_connected:
|
|
# send_command 方法来自 SerialManager 类
|
|
select_all_bytes = self.serial_protocol.select_all()
|
|
|
|
print(select_all_bytes)
|
|
|
|
if not select_all_bytes:
|
|
logger.error("指令封装失败,数据无效")
|
|
return
|
|
|
|
# send_command 方法来自 SerialManager 类
|
|
success = self.serial_manager.send_command(select_all_bytes)
|
|
|
|
if success:
|
|
|
|
click_labels = ScreenLabel.click_labels
|
|
|
|
# 1. 查找对应的 Label 对象
|
|
# label = self.screen_labels[screen_id - 1] # 数组下标从0开始
|
|
|
|
if click_labels and screen_id in click_labels:
|
|
for click_label in click_labels:
|
|
label = self.screen_labels[click_label - 1] # 数组下标从0开始
|
|
|
|
# 2. 修改显示文字和样式
|
|
label.setText(f"Screen {click_label}\n[{source['name']}]\n(已分配)")
|
|
label.setStyleSheet("""
|
|
background-color: rgb(0, 255, 127); /* 绿色背景 */
|
|
color: black;
|
|
border: 2px solid white;
|
|
font-weight: bold;
|
|
""")
|
|
|
|
# 3. 这里调用核心控制器发送指令
|
|
# self.matrix.send_layout_command([screen_id], source)
|
|
|
|
if ScreenLabel.split_solution[click_label - 1]:
|
|
ScreenLabel.split_solution[click_label - 1]['status'] = 2
|
|
ScreenLabel.split_solution[click_label - 1]['source_type'] = source['type']
|
|
ScreenLabel.split_solution[click_label - 1]['source_id'] = source['id']
|
|
|
|
print(f"【指令】屏幕 {click_label} 已切换至 {source['name']}")
|
|
else:
|
|
label = self.screen_labels[screen_id - 1] # 数组下标从0开始
|
|
|
|
# 2. 修改显示文字和样式
|
|
label.setText(f"Screen {screen_id}\n[{source['name']}]\n(已分配)")
|
|
label.setStyleSheet("""
|
|
background-color: rgb(0, 255, 127); /* 绿色背景 */
|
|
color: black;
|
|
border: 2px solid white;
|
|
font-weight: bold;
|
|
""")
|
|
|
|
# 3. 这里调用核心控制器发送指令
|
|
# self.matrix.send_layout_command([screen_id], source)
|
|
|
|
if ScreenLabel.split_solution[screen_id - 1]:
|
|
ScreenLabel.split_solution[screen_id - 1]['status'] = 2
|
|
ScreenLabel.split_solution[screen_id - 1]['source_type'] = source['type']
|
|
ScreenLabel.split_solution[screen_id - 1]['source_id'] = source['id']
|
|
|
|
print(f"【指令】屏幕 {screen_id} 已切换至 {source['name']}")
|
|
|
|
ScreenLabel.click_labels = []
|
|
|
|
logger.info(f"✅ 指令发送成功")
|
|
else:
|
|
logger.error("指令发送失败")
|
|
|
|
else:
|
|
logger.error("指令发送失败,未连接数据大屏")
|
|
return
|
|
|
|
# # 3. 这里调用核心控制器发送指令
|
|
# # self.matrix.send_layout_command([screen_id], source)
|
|
# print(f"【指令】屏幕 {screen_id} 已切换至 {source}")
|
|
|
|
def set_split(self, screen_id):
|
|
"""
|
|
设置屏幕控件的拼接状态
|
|
"""
|
|
# self.update_style()
|
|
|
|
# 获取选中的屏幕控件
|
|
selected_widgets = [self.screen_labels[value - 1] for value in ScreenLabel.click_labels]
|
|
print(selected_widgets)
|
|
|
|
# 生成拼接指令参数
|
|
params = self.serial_protocol.calculate_mosaic_params(selected_widgets)
|
|
print(params)
|
|
|
|
# 2. 【新增】通过串口管理器发送
|
|
# 这里的 self.serial_manager 来自于我们在 main.py 中的初始化
|
|
if hasattr(self, 'serial_manager') and self.serial_manager.is_connected:
|
|
start = params['start']
|
|
v_count = params['v_count']
|
|
h_count = params['h_count']
|
|
|
|
# 计算拼接id
|
|
big_pic_id = 1
|
|
for i in range(start, start + v_count * h_count):
|
|
if ScreenLabel.split_solution[i]['status'] == 3 and ScreenLabel.split_solution[i]['big_pic_id'] > 0:
|
|
big_pic_id += 1
|
|
break
|
|
|
|
# 生成拼接指令
|
|
mosaic_packet_bytes = self.serial_protocol.build_mosaic_packet(start, v_count, h_count, big_pic_id)
|
|
|
|
print(mosaic_packet_bytes)
|
|
|
|
if not mosaic_packet_bytes:
|
|
logger.error("指令封装失败,数据无效")
|
|
return
|
|
|
|
# send_command 方法来自 SerialManager 类
|
|
success = self.serial_manager.send_command(mosaic_packet_bytes)
|
|
|
|
if success:
|
|
|
|
click_labels = ScreenLabel.click_labels
|
|
|
|
# 1. 查找对应的 Label 对象
|
|
# label = self.screen_labels[screen_id - 1] # 数组下标从0开始
|
|
|
|
logger.info(f"✅ 指令发送成功")
|
|
else:
|
|
logger.error("指令发送失败")
|
|
|
|
else:
|
|
logger.error("指令发送失败,未连接数据大屏")
|
|
return
|
|
|
|
|
|
# if selected:
|
|
# # 如果选中,设置一个红色/蓝色的边框,或者背景色
|
|
# self.setStyleSheet("""
|
|
# border: 2px solid red;
|
|
# background-color: rgba(255, 0, 0, 0.1);
|
|
# """)
|
|
# else:
|
|
# # 如果取消选中,恢复默认样式(假设默认是灰色边框)
|
|
# self.setStyleSheet("""
|
|
# border: 1px solid gray;
|
|
# background-color: white;
|
|
# """)
|
|
|
|
def clear_screen(self, screen_id):
|
|
|
|
screen_pos = ScreenLabel.split_solution[screen_id - 1]['big_pic_id']
|
|
screen_status = ScreenLabel.split_solution[screen_id - 1]['status']
|
|
|
|
if screen_pos > 0 and screen_status > 0:
|
|
for key, value in enumerate(ScreenLabel.split_solution):
|
|
if value['big_pic_id'] == screen_pos:
|
|
ScreenLabel.split_solution[key]['status'] = 0
|
|
ScreenLabel.split_solution[key]['big_pic_id'] = 0
|
|
|
|
label = self.screen_labels[key]
|
|
|
|
# 切换选中状态
|
|
label.setText(f"Screen {key + 1}\n(空闲)")
|
|
label.set_selected(False)
|
|
label.update_style()
|
|
|
|
print(f"【指令】屏幕 {key+1} 已清屏")
|
|
|
|
else:
|
|
ScreenLabel.split_solution[screen_id - 1]['status'] = 0
|
|
ScreenLabel.split_solution[screen_id - 1]['big_pic_id'] = 0
|
|
|
|
label = self.screen_labels[screen_id - 1]
|
|
|
|
# 切换选中状态
|
|
label.setText(f"Screen {screen_id}\n(空闲)")
|
|
label.set_selected(False)
|
|
label.update_style()
|
|
|
|
print(f"【指令】屏幕 {screen_id} 已清屏")
|
|
|
|
def mouse_press_event(self, event):
|
|
# 鼠标按下时记录起点,显示选框
|
|
self.origin = event.pos()
|
|
self.rubber_band.setGeometry(QRect(self.origin, QSize()))
|
|
self.rubber_band.show()
|
|
|
|
def mouse_move_event(self, event):
|
|
# 鼠标移动时调整选框大小
|
|
if self.rubber_band.isVisible():
|
|
rect = QRect(self.origin, event.pos()).normalized()
|
|
self.rubber_band.setGeometry(rect)
|
|
|
|
def mouse_release_event(self, event):
|
|
# 鼠标释放时,隐藏选框,并检查选中了哪些屏幕
|
|
self.rubber_band.hide()
|
|
|
|
# 获取选框的范围
|
|
select_rect = self.rubber_band.geometry()
|
|
|
|
try:
|
|
# ... 你的框选逻辑 ...
|
|
logger.debug(f"鼠标释放,开始计算拼接参数")
|
|
except Exception as e:
|
|
logger.error(f"框选事件处理失败: {str(e)}")
|
|
|
|
# 1. 先取消所有屏幕的选中状态
|
|
# for screen_widget in self.screen_labels:
|
|
# screen_widget.set_selected(False)
|
|
|
|
# 遍历所有屏幕,检查是否被选框包含
|
|
for key, screen_widget in enumerate(self.screen_labels): # 假设你把所有屏幕实例存进了这个列表
|
|
# 获取屏幕在容器内的位置
|
|
screen_rect = screen_widget.geometry()
|
|
# 如果屏幕在选框内
|
|
if select_rect.contains(screen_rect.center()):
|
|
screen_widget.set_selected(True) # 调用你之前写的选中方法
|
|
else:
|
|
if ScreenLabel.split_solution[key]['status'] < 2:
|
|
screen_widget.set_selected(False)
|
|
|
|
def send_mosaic_command(self, start, hcount, vcount):
|
|
print(f"当前 serial_manager 对象: {id(self.serial_manager)}")
|
|
print(f"当前 is_connected 状态: {self.serial_manager.is_connected}")
|
|
|
|
try:
|
|
print(f"准备发送指令: Start={start}, {hcount}x{vcount}")
|
|
|
|
# 1. 【新增】使用协议模块封装数据
|
|
command_bytes = build_mosaic_packet(start, hcount, vcount)
|
|
|
|
if not command_bytes:
|
|
logger.error("指令封装失败,数据无效")
|
|
return
|
|
|
|
# 2. 【新增】通过串口管理器发送
|
|
# 这里的 self.serial_manager 来自于我们在 main.py 中的初始化
|
|
if hasattr(self, 'serial_manager') and self.serial_manager.is_connected:
|
|
# send_command 方法来自 SerialManager 类
|
|
success = self.serial_manager.send_command(command_bytes)
|
|
if success:
|
|
logger.info(f"✅ 指令发送成功: {hcount}x{vcount} 拼接")
|
|
else:
|
|
logger.error("指令发送失败")
|
|
else:
|
|
logger.warning("⚠️ 未连接设备,请先在连接面板中连接串口")
|
|
# 可以弹窗提示用户
|
|
# QMessageBox.warning(self, "警告", "设备未连接!")
|
|
|
|
except Exception as e:
|
|
logger.error(f"执行拼接指令时出错: {e}")
|
|
|
|
# 2. 【核心】发送硬件指令:调用你之前的串口/网络发送函数
|
|
# 假设你有一个 send_to_device(data) 函数
|
|
# command_data = self.generate_command_data(start, hcount, vcount)
|
|
# self.send_to_device(command_data)
|
|
|
|
# 3. 【提示】给用户反馈
|
|
# QMessageBox.information(self, "成功", f"已切换到布局: {hcount}x{vcount}")
|
|
|
|
def update_screen_selection_visual(self, start, hcount, vcount):
|
|
"""
|
|
根据拼接参数,更新界面上屏幕的选中(高亮)状态。
|
|
"""
|
|
# 1. 先取消所有屏幕的选中状态
|
|
for screen_widget in self.screen_widgets_list:
|
|
screen_widget.set_selected(False)
|
|
|
|
# 2. 计算当前拼接区域覆盖了哪些屏幕
|
|
# 假设总共有 4 列(根据你的实际情况修改)
|
|
cols = 4
|
|
start_row = start // cols
|
|
start_col = start % cols
|
|
|
|
# 3. 遍历逻辑矩阵,将对应的物理屏幕设置为选中
|
|
for vr in range(vcount): # 垂直方向
|
|
for hr in range(hcount): # 水平方向
|
|
phy_row = start_row + vr
|
|
phy_col = start_col + hr
|
|
index = phy_row * cols + phy_col
|
|
|
|
# 防止越界
|
|
if 0 <= index < len(self.screen_widgets_list):
|
|
self.screen_widgets_list[index].set_selected(True)
|
|
|
|
print(f"视觉更新完成: Start={start}, {hcount}x{vcount}")
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
window = MatrixControlApp()
|
|
window.show()
|
|
sys.exit(app.exec_())
|