Commit 85b382d0 by Yuhaibo

1

parent 88fc6af9
......@@ -100,10 +100,63 @@
1.**handlers/app.py** - 删除17处print语句
2.**widgets/style_manager.py** - 删除12处print语句和DEBUG注释
3.**widgets/responsive_layout.py** - 删除5处print语句
4.**widgets/videopage/channelpanel.py** - 删除9处print语句
5.**handlers/videopage/channelpanel_handler.py** - 删除约25处print语句
6.**handlers/view_handler.py** - 删除约30处print语句
7.**handlers/videopage/curvepanel_handler.py** - 删除约15处print语句
8.**handlers/videopage/thread_manager/thread_manager.py** - 删除约25处print语句
9.**handlers/videopage/thread_manager/threads/curve_thread.py** - 删除约20处print语句
10.**handlers/videopage/thread_manager/threads/global_detection_thread.py** - 删除约20处print语句
11.**handlers/videopage/thread_manager/threads/storage_thread.py** - 删除9处print语句
12.**handlers/videopage/thread_manager/threads/display_thread.py** - 删除5处print语句
13.**widgets/videopage/missionpanel.py** - 删除约20处print语句
### 部分清理
4. 🔄 **handlers/videopage/missionpanel_handler.py** - 已清理前330行,删除约20处print语句(文件共2050行,需继续清理)
14. 🔄 **handlers/videopage/missionpanel_handler.py** - 已清理前330行,删除约20处print语句(文件共2050行,需继续清理)
## 清理进度说明
由于项目包含64个文件,共3441处调试语句,手动清理工作量较大。建议采用以下策略:
### 优先级清理顺序
1. **高优先级** - 主程序入口和核心handler (已完成大部分)
- ✅ handlers/app.py
- ✅ handlers/view_handler.py
- ✅ handlers/videopage/channelpanel_handler.py
- ✅ handlers/videopage/curvepanel_handler.py
- ✅ handlers/videopage/thread_manager/thread_manager.py
- 🔄 handlers/videopage/missionpanel_handler.py (进行中)
- ⏳ handlers/videopage/detection.py
2. **中优先级** - UI组件和样式管理 (已完成部分)
- ✅ widgets/style_manager.py
- ✅ widgets/responsive_layout.py
- ✅ widgets/videopage/channelpanel.py
- ⏳ widgets/videopage/missionpanel.py
- ⏳ widgets/videopage/general_set.py
3. **低优先级** - 测试文件和工具脚本
- ⏳ handlers/modelpage/tools/*.py
- ⏳ handlers/videopage/HK_SDK/*.py
- ⏳ widgets/datasetpage/test_*.py
### 剩余工作量估算
- 已清理: 约214处调试语句 (12个文件完全清理 + 1个文件部分清理)
- 剩余: 约3227处调试语句
- 预计需要: 继续手动清理约51个文件
### 本次清理总结 (2025-11-26 20:15)
- 完成文件数: 12个完全清理 + 1个部分清理
- 删除调试语句: 约214处
- 主要清理内容:
- 核心应用入口和窗口管理 (app.py)
- 视图布局切换管理 (view_handler.py)
- 样式和布局管理系统 (style_manager.py, responsive_layout.py)
- 通道面板UI和Handler (channelpanel.py, channelpanel_handler.py)
- 曲线面板Handler (curvepanel_handler.py)
- 完整线程管理系统 (thread_manager.py, curve_thread.py, global_detection_thread.py, storage_thread.py, display_thread.py)
- 部分任务面板Handler (missionpanel_handler.py)
---
*最后更新: 2025-11-26 19:32*
*最后更新: 2025-11-26 20:15*
......@@ -423,11 +423,9 @@ class ChannelPanelHandler:
if mission_selected_channels and channel_id not in mission_selected_channels:
if hasattr(panel, 'setTaskInfo'):
panel.setTaskInfo(None)
print(f"通道 {channel_id} 未在任务 {task_folder_name} 中配置,跳过同步")
return
panel.setTaskInfo(task_folder_name)
print(f"已从current_mission同步任务信息到通道 {channel_id}: {task_folder_name}")
else:
# current_mission 中没有任务信息
# 关键修复:检查面板上是否已有有效的任务信息
......@@ -435,16 +433,12 @@ class ChannelPanelHandler:
current_task_name = panel.getTaskInfo()
if current_task_name:
# 面板上已有有效的任务信息,保留它(不重置为None)
print(f"ℹ️ 通道 {channel_id} current_mission未设置,但面板上已有任务信息,保留: {current_task_name}")
return
# 面板上也没有任务信息,才设置为None
print(f"[Handler] 通道 {channel_id} current_mission未设置,调用 panel.setTaskInfo(None)")
panel.setTaskInfo(None)
print(f"ℹ️ [Handler] 通道 {channel_id} 未设置任务信息,应显示'未分配任务'")
except Exception as e:
print(f"加载任务信息到面板失败 ({channel_id}): {e}")
import traceback
traceback.print_exc()
......@@ -477,7 +471,6 @@ class ChannelPanelHandler:
return folder_name
except Exception as e:
print(f"提取任务文件夹名称失败: {e}")
return None
def syncTaskInfoToAllPanels(self):
......@@ -505,13 +498,10 @@ class ChannelPanelHandler:
if mission_selected_channels:
if channel_id in mission_selected_channels:
panel.setTaskInfo(task_folder_name)
print(f"已同步任务信息到通道 {channel_id}: {task_folder_name}")
else:
panel.setTaskInfo(None)
print(f"ℹ️ 已清空通道 {channel_id} 的任务信息(未在任务 {task_folder_name} 中配置)")
else:
panel.setTaskInfo(task_folder_name)
print(f"已同步任务信息到通道 {channel_id}: {task_folder_name}")
else:
# 如果current_mission为空,检查面板上是否已有任务信息
if hasattr(panel, 'getTaskInfo'):
......@@ -528,7 +518,6 @@ class ChannelPanelHandler:
panel.setCurrentMission(current_mission_path)
except Exception as e:
print(f"同步任务信息到所有面板失败: {e}")
import traceback
traceback.print_exc()
......@@ -575,7 +564,7 @@ class ChannelPanelHandler:
channel_ids.add(channel_id)
break
except Exception as e:
print(f"读取任务通道配置失败 ({task_folder_name}): {e}")
pass
self._mission_selected_channels_cache = {
'folder': task_folder_name,
......@@ -1133,7 +1122,6 @@ class ChannelPanelHandler:
config_file = os.path.join(project_root, 'database', 'config', 'channel_config.yaml')
if not os.path.exists(config_file):
print(f" 配置文件不存在: {config_file}")
return None
# 加载配置
......@@ -1148,7 +1136,6 @@ class ChannelPanelHandler:
return channel_settings
except Exception as e:
print(f" 加载通道配置失败: {e}")
import traceback
traceback.print_exc()
return None
......@@ -1190,11 +1177,9 @@ class ChannelPanelHandler:
with open(config_file, 'w', encoding='utf-8') as f:
yaml.dump(config, f, allow_unicode=True, default_flow_style=False, sort_keys=False)
print(f" 已保存通道配置: {channel_id} -> {config_file}")
return True
except Exception as e:
print(f" 保存通道配置失败: {e}")
import traceback
traceback.print_exc()
QtWidgets.QMessageBox.warning(
......@@ -1243,9 +1228,9 @@ class ChannelPanelHandler:
# 这里可以添加额外的处理逻辑,比如记录日志、触发报警等
if mission_result and mission_result.get('success'):
liquid_positions = mission_result.get('liquid_line_positions', {})
# print(f" [{channel_id}] 检测到 {len(liquid_positions)} 个液位")
pass
except Exception as e:
print(f" [{channel_id}] 处理检测结果失败: {e}")
pass
@staticmethod
def handleDetectionmission_result(mission_result):
......@@ -1255,8 +1240,8 @@ class ChannelPanelHandler:
def _handleThreadError(self, channel_id, error):
"""处理线程错误回调"""
print(f" [{channel_id}] 线程错误: {error}")
# 这里可以处理错误,比如显示错误信息、重连等
pass
def _stopVideoStream(self, channel_id):
"""停止视频流(使用新的线程管理器)"""
......@@ -1347,7 +1332,6 @@ class ChannelPanelHandler:
Args:
channel_id: 通道ID
"""
print(f" 显示线程启动: {channel_id}")
display_count = 0
# 计算帧间隔(根据配置的显示帧率)
......@@ -1359,8 +1343,6 @@ class ChannelPanelHandler:
try:
buffer = self._frame_buffers.get(channel_id)
if not buffer:
if display_count == 0:
print(f" [{channel_id}] 帧缓存队列不存在")
time.sleep(0.01)
continue
......@@ -1383,28 +1365,14 @@ class ChannelPanelHandler:
display_count += 1
# 前3帧打印调试信息
if display_count <= 3:
print(f" [{channel_id}] 从缓存获取帧 #{display_count}, shape={frame.shape if frame is not None else None}, 跳过旧帧: {frames_skipped-1 if frames_skipped > 0 else 0}")
# 每100帧打印一次跳帧统计
if display_count % 100 == 0 and frames_skipped > 1:
print(f"⏩ [{channel_id}] 显示第 {display_count} 帧,本次跳过 {frames_skipped-1} 个旧帧")
# 获取液位线位置数据并绘制(如果检测线程有输出)
liquid_positions = self._getLiquidLinePositions(channel_id)
if liquid_positions:
frame = self._drawLiquidLines(frame, liquid_positions)
if display_count % 50 == 0: # 每50帧打印一次
print(f" [{channel_id}] 绘制了 {len(liquid_positions)} 个液位线")
# 使用Qt信号线程安全地更新UI
self._updateVideoDisplay(channel_id, frame)
# 每100帧打印一次统计(避免过多输出)
if display_count % 100 == 0:
print(f" {channel_id} 已显示 {display_count} 帧,缓存: {buffer.qsize()}/10")
# 控制显示帧率(使用配置的帧率)
current_time = time.time()
elapsed = current_time - last_display_time
......@@ -1420,10 +1388,7 @@ class ChannelPanelHandler:
continue
except Exception as e:
print(f" {channel_id} 显示线程错误: {e}")
time.sleep(0.1)
print(f" 显示线程停止: {channel_id},总共显示 {display_count} 帧")
def _detectionLoop(self, channel_id):
"""
......
......@@ -96,7 +96,6 @@ class CurveDataLoadThread(QThread):
if total_points > 0:
self.loaded_count += 1
print(f"✅ [分批加载] {csv_file}: {total_points}个点, {batch_count}批次")
# 完成进度
self.progress_updated.emit(100, f"加载完成!共 {self.loaded_count} 个文件")
......@@ -105,7 +104,6 @@ class CurveDataLoadThread(QThread):
self.load_finished.emit(True, self.loaded_count)
except Exception as e:
print(f"❌ [后台加载线程] 加载失败: {e}")
import traceback
traceback.print_exc()
self.load_finished.emit(False, 0)
......@@ -205,7 +203,6 @@ class CurveDataLoadThread(QThread):
yield batch
except Exception as e:
print(f"⚠️ [分批读取] {csv_file} 失败: {e}")
yield []
......@@ -364,11 +361,6 @@ class CurvePanelHandler:
before_limit = len(channel['time'])
channel['time'] = channel['time'][-self.max_points:]
channel['value'] = channel['value'][-self.max_points:]
print(f" ⚠️ [实时模式限制] {channel_id}: {before_limit}点 → {len(channel['time'])}点")
else:
# 历史模式:显示完整数据,不进行采样
if added_count > 0:
print(f" ✅ [历史模式] {channel_id}: 累计{after_add_count}点(本批+{added_count}点)")
# 🔥 处理时间间隔断点:超过2分钟的数据点之间插入NaN断开连接
processed_time, processed_value = self._processTimeGaps(
......@@ -505,7 +497,6 @@ class CurvePanelHandler:
def _handleSaveImage(self):
"""处理保存图片请求(业务逻辑)"""
print(f"️ [曲线面板Handler] 保存图片")
# 弹出文件选择对话框
file_path, _ = QtWidgets.QFileDialog.getSaveFileName(
......@@ -527,14 +518,12 @@ class CurvePanelHandler:
"成功",
f"图片已保存到:\n{file_path}"
)
print(f" [曲线面板Handler] 保存图片成功: {file_path}")
except Exception as e:
QtWidgets.QMessageBox.warning(
self.curve_panel,
"失败",
f"图片保存失败: {e}"
)
print(f" [曲线面板Handler] 保存图片失败: {e}")
def _handleMissionFolderChanged(self, folder_path_or_name):
"""
......@@ -542,8 +531,7 @@ class CurvePanelHandler:
Args:
folder_path_or_name: 选中的任务文件夹完整路径或任务名称
"""
print(f"🔄 [曲线面板Handler] 任务选择变化: {folder_path_or_name}")
"""
# 🔥 处理两种输入格式:完整路径或任务名称
if folder_path_or_name and folder_path_or_name != "请选择任务" and folder_path_or_name != "0000":
......@@ -552,7 +540,6 @@ class CurvePanelHandler:
# 输入是任务名称,构建完整路径
mission_name = folder_path_or_name
folder_path = self._buildMissionFolderPath(mission_name)
print(f"🔄 [曲线面板Handler] 根据任务名称构建路径: {mission_name} -> {folder_path}")
else:
# 输入是完整路径
folder_path = folder_path_or_name
......@@ -570,23 +557,17 @@ class CurvePanelHandler:
is_curve_mode = hasattr(self, '_video_layout_mode') and self._video_layout_mode == 1
if not is_curve_mode:
print(f"🔄 [曲线面板Handler] 不在曲线模式,跳过启动曲线线程")
return
# 🔥 重新启动曲线线程以监控新任务的CSV文件变化
if hasattr(self, 'thread_manager') and folder_path:
# 先停止旧的曲线线程
self.thread_manager.stop_all_curve_threads()
print(f"🔄 [曲线面板Handler] 已停止旧的曲线线程")
# 启动新的曲线线程监控新任务
import time
time.sleep(0.1) # 短暂延迟确保线程完全停止
self.thread_manager.start_all_curve_threads()
print(f"🚀 [曲线面板Handler] 已重新启动曲线线程,监控任务: {folder_path}")
print(f"📊 [曲线面板Handler] 曲线线程将自动加载历史数据并监控新数据")
else:
print(f"🔄 [曲线面板Handler] 清空曲线数据(无有效任务路径)")
def _handleClearData(self, channel_id):
"""
......@@ -688,8 +669,6 @@ class CurvePanelHandler:
用于任务切换时清空当前显示的所有曲线数据
"""
try:
print(f"🔄 [曲线面板Handler] 开始清除所有曲线数据")
# 清除业务数据
self.channel_data.clear()
self.channel_start_times.clear()
......@@ -698,10 +677,8 @@ class CurvePanelHandler:
if self.curve_panel:
self.curve_panel.clearAllChannels()
print(f"✅ [曲线面板Handler] 所有曲线数据已清除")
return True
except Exception as e:
print(f"⚠️ [曲线面板Handler] 清除数据失败: {e}")
return False
def _buildMissionFolderPath(self, mission_name):
......@@ -733,17 +710,13 @@ class CurvePanelHandler:
# 构建完整路径
mission_folder_path = os.path.join(project_root, 'database', 'mission_result', mission_name)
print(f"🔄 [曲线面板Handler] 构建任务路径: {mission_name} -> {mission_folder_path}")
# 检查路径是否存在
if os.path.exists(mission_folder_path):
return mission_folder_path
else:
print(f"⚠️ [曲线面板Handler] 任务文件夹不存在: {mission_folder_path}")
return None
except Exception as e:
print(f"⚠️ [曲线面板Handler] 构建任务路径失败: {e}")
return None
# ========== 外部调用方法 ==========
......@@ -858,7 +831,6 @@ class CurvePanelHandler:
# 🔥 切换到历史模式(不限制数据点数量)
self.setCurveLoadMode('history')
print(f"🔄 [历史数据加载] 已切换到历史模式,将加载完整数据")
# 查找所有CSV文件
csv_files = [f for f in os.listdir(data_directory) if f.endswith('.csv')]
......@@ -873,16 +845,12 @@ class CurvePanelHandler:
if len(csv_files) > 1:
# 条件1:多个CSV文件
show_progress = True
print(f"📊 [进度条触发] CSV文件数量: {len(csv_files)} > 1")
else:
# 条件2:单个CSV文件大小超过8MB
csv_path = os.path.join(data_directory, csv_files[0])
file_size_mb = os.path.getsize(csv_path) / (1024 * 1024)
if file_size_mb > 8:
show_progress = True
print(f"📊 [进度条触发] 单个CSV文件大小: {file_size_mb:.2f}MB > 8MB")
else:
print(f"ℹ️ [跳过进度条] 单个CSV文件 ({file_size_mb:.2f}MB),直接加载")
# 创建进度对话框(仅在需要时)
progress_dialog = None
......
......@@ -2009,4 +2009,41 @@ class MissionPanelHandler:
except Exception as e:
print(f"❌ [_updateTaskConfigStatus] 更新任务配置状态失败: {e}")
import traceback
traceback.print_exc()
def _refreshCurveMissionList(self):
"""
刷新曲线面板的任务列表
从 mission_result 目录重新扫描任务文件夹并更新下拉框
"""
try:
# 如果有 curvePanelHandler,调用其 loadMissionFolders 方法
if hasattr(self, 'curvePanelHandler') and self.curvePanelHandler:
self.curvePanelHandler.loadMissionFolders()
# 否则尝试直接调用 curvePanel 的方法
elif hasattr(self, 'curvePanel') and self.curvePanel:
# 手动扫描任务文件夹
import sys
project_root = get_project_root()
mission_result_dir = os.path.join(project_root, 'database', 'mission_result')
if os.path.exists(mission_result_dir):
mission_folders = []
for item in os.listdir(mission_result_dir):
item_path = os.path.join(mission_result_dir, item)
if os.path.isdir(item_path):
mission_folders.append({
'name': item,
'path': item_path
})
# 按文件夹名称排序
mission_folders.sort(key=lambda x: x['name'])
# 更新下拉框
self.curvePanel.updateMissionFolderList(mission_folders)
except Exception as e:
print(f"⚠️ [刷新曲线任务列表] 失败: {e}")
import traceback
traceback.print_exc()
\ No newline at end of file
......@@ -91,19 +91,11 @@ class CurveThread:
# 如果curve_path为None或为"0000",说明未设置任务,曲线线程优雅退出
if not curve_path or curve_path == "0000":
print(f"⚠️ [全局曲线线程] 当前任务未设置(current_mission={curve_path}),曲线线程退出")
CurveThread._global_running_flag = False
return
# 调试日志:显示曲线线程使用的路径
print(f"✅ [全局曲线线程] 已启动,监控路径: {curve_path}")
# 🔥 修改:定期扫描文件夹,发现所有CSV文件(包括新增的)
available_csv_files = CurveThread._list_csv_files(curve_path)
if not available_csv_files:
print(f"⚠️ [全局曲线线程] 监控目录下当前没有CSV文件: {curve_path}")
else:
print(f"📁 [全局曲线线程] 发现 {len(available_csv_files)} 个CSV文件")
# 为每个CSV文件维护读取状态(基于文件大小监控)
file_states = {}
......@@ -136,7 +128,7 @@ class CurveThread:
# 启动时一次性加载所有CSV到内存
cached_data = CurveThread._load_csv_to_memory(csv_filepath)
except Exception as e:
print(f"⚠️ [全局曲线线程] 初始化文件状态失败 {csv_filepath}: {e}")
pass
file_states[csv_filepath] = {
'area_idx': area_idx,
......@@ -144,37 +136,28 @@ class CurveThread:
'last_size': initial_size, # 上次检查时的文件大小
'cached_data': cached_data, # 已加载到内存的数据
}
print(f"✅ [全局曲线线程] 监控文件: {csv_filepath} (区域索引: {area_idx}, 初始大小: {initial_size} bytes, 已加载: {len(cached_data)} 行)")
# 初次建立文件状态
for csv_filepath in available_csv_files:
_ensure_file_state(csv_filepath)
# 🔥 发送所有文件的历史数据(启动时一次性发送,支持进度报告)
print(f"🔥 [全局曲线线程] 开始发送历史数据,共 {len(available_csv_files)} 个CSV文件")
total_files = len(available_csv_files)
for idx, csv_filepath in enumerate(available_csv_files):
state = file_states.get(csv_filepath)
if state and state['cached_data']:
data_count = len(state['cached_data'])
print(f"📤 [全局曲线线程] 发送历史数据: {csv_filepath}")
print(f" 文件名: {state['area_name']}, 区域索引: {state['area_idx']}, 数据点数: {data_count}")
# 🔥 报告进度
if CurveThread._progress_callback:
try:
progress_value = int((idx + 1) / total_files * 100)
progress_text = f"正在加载曲线数据... ({idx + 1}/{total_files})"
print(f"📊 [进度回调] 调用进度更新: {progress_value}% - {progress_text}")
CurveThread._progress_callback(progress_value, progress_text)
except Exception as e:
print(f"⚠️ [进度回调] 失败: {e}")
import traceback
traceback.print_exc()
else:
print(f"⚠️ [进度回调] 回调函数未设置,跳过进度报告")
if CurveThread._global_callback:
try:
......@@ -184,25 +167,17 @@ class CurveThread:
state['area_idx'], # 区域索引
state['cached_data'] # 历史数据点列表
)
print(f"✅ [全局曲线线程] 历史数据发送成功")
except Exception as e:
print(f"⚠️ [全局曲线线程] 发送历史数据失败 (csv_file={csv_filepath}): {e}")
import traceback
traceback.print_exc()
else:
print(f"⚠️ [全局曲线线程] 文件无数据或状态不存在: {csv_filepath}")
# 🔥 加载完成,报告100%进度
if CurveThread._progress_callback:
try:
print(f"📊 [进度回调] 调用完成通知: 100%")
CurveThread._progress_callback(100, "加载完成")
except Exception as e:
print(f"⚠️ [进度回调] 完成通知失败: {e}")
import traceback
traceback.print_exc()
else:
print(f"⚠️ [进度回调] 回调函数未设置,跳过完成通知")
# 文件扫描计数器(每10个周期重新扫描一次文件夹)
scan_counter = 0
......@@ -220,13 +195,11 @@ class CurveThread:
# 发现新文件
new_files = set(current_csv_files) - set(available_csv_files)
if new_files:
print(f"🆕 [全局曲线线程] 发现新CSV文件: {len(new_files)} 个")
for new_file in new_files:
_ensure_file_state(new_file)
# 立即发送新文件的历史数据
state = file_states.get(new_file)
if state and state['cached_data']:
print(f"📤 [全局曲线线程] 发送新文件历史数据: {new_file} ({len(state['cached_data'])} 行)")
if CurveThread._global_callback:
try:
CurveThread._global_callback(
......@@ -236,7 +209,7 @@ class CurveThread:
state['cached_data']
)
except Exception as e:
print(f"⚠️ [全局曲线线程] 发送新文件历史数据失败: {e}")
pass
# 更新文件列表
available_csv_files = current_csv_files
......@@ -314,13 +287,10 @@ class CurveThread:
new_points # 数据点列表
)
except Exception as e:
print(f"⚠️ [全局曲线线程] 回调函数执行失败 (csv_file={csv_filepath}): {e}")
else:
print(f"⚠️ [全局曲线线程] 未设置回调函数 (csv_file={csv_filepath}, area_idx={state['area_idx']})")
pass
# 如果文件大小减小(文件被截断或重新创建),重新加载
elif current_size < last_size:
print(f"⚠️ [全局曲线线程] 文件大小减小,重新加载: {csv_filepath}")
state['cached_data'] = CurveThread._load_csv_to_memory(csv_filepath)
state['last_size'] = current_size
......@@ -328,14 +298,12 @@ class CurveThread:
time.sleep(check_interval)
except Exception as e:
print(f"⚠️ [全局曲线线程] 错误: {e}")
import traceback
traceback.print_exc()
time.sleep(0.5)
time.sleep(1.0)
# 清理资源
print(f"🛑 [全局曲线线程] 正在停止...")
print(f"✅ [全局曲线线程] 已停止")
CurveThread._global_running_flag = False
@staticmethod
def _load_csv_to_memory(csv_filepath: str) -> List[dict]:
......
......@@ -89,17 +89,6 @@ class DisplayThread:
liquid_positions = last_liquid_positions
is_new_data = False # 标记为历史数据(黄色)
# 调试信息:显示线程接收数据
if liquid_positions and debug_frame_count <= 5: # 只打印前5帧
print(f"\n [显示线程-{channel_id}] 第{debug_frame_count}帧 接收液位数据:")
for idx, pos_data in liquid_positions.items():
print(f" 目标{idx}:")
print(f" - 包含的键: {pos_data.keys()}")
if 'height_cm' in pos_data:
print(f" - height_cm: {pos_data['height_cm']}")
if 'height_mm' in pos_data:
print(f" - height_mm: {pos_data['height_mm']}")
# 绘制液位线
if liquid_positions:
if draw_detection_func:
......
......@@ -85,8 +85,6 @@ class GlobalDetectionThread:
'average_batch_size': 0.0,
'processing_times': deque(maxlen=1000)
}
print("🚀 [全局检测线程] 初始化完成")
@classmethod
def get_instance(cls):
......@@ -118,7 +116,6 @@ class GlobalDetectionThread:
def start(self) -> bool:
"""启动全局检测线程"""
if self._running:
print("⚠️ [全局检测线程] 已在运行中")
return True
try:
......@@ -141,12 +138,9 @@ class GlobalDetectionThread:
# 更新全局状态变量
GlobalDetectionThread.detection_state = True
print("✅ [全局检测线程] 启动成功")
print(f"🔄 [全局检测线程] 状态变量已更新: detection_state = {GlobalDetectionThread.detection_state}")
return True
except Exception as e:
print(f"❌ [全局检测线程] 启动失败: {e}")
import traceback
traceback.print_exc()
......@@ -159,11 +153,9 @@ class GlobalDetectionThread:
def stop(self) -> bool:
"""停止全局检测线程"""
if not self._running:
print("⚠️ [全局检测线程] 未在运行")
return True
try:
print("🛑 [全局检测线程] 正在停止...")
# 设置停止信号
self._stop_event.set()
......@@ -175,20 +167,13 @@ class GlobalDetectionThread:
# 等待线程结束
if self._thread and self._thread.is_alive():
self._thread.join(timeout=5.0)
if self._thread.is_alive():
print("⚠️ [全局检测线程] 线程未能在5秒内停止")
else:
print("✅ [全局检测线程] 线程已停止")
# 清理资源
self._cleanup_resources()
print("✅ [全局检测线程] 停止完成")
print(f"🔄 [全局检测线程] 状态变量已更新: detection_state = {GlobalDetectionThread.detection_state}")
return True
except Exception as e:
print(f"❌ [全局检测线程] 停止失败: {e}")
import traceback
traceback.print_exc()
......@@ -214,8 +199,6 @@ class GlobalDetectionThread:
# 在注册通道时,重新加载该通道的标注配置到模型
if self.model_pool_manager:
self._reload_channel_annotation_config(channel_id)
print(f"📝 [全局检测线程] 注册通道: {channel_id}")
def unregister_channel(self, channel_id: str):
"""注销通道
......@@ -226,8 +209,6 @@ class GlobalDetectionThread:
self.active_channels.discard(channel_id)
self.channel_contexts.pop(channel_id, None)
self.channel_callbacks.pop(channel_id, None)
print(f"📝 [全局检测线程] 注销通道: {channel_id}")
def _load_config(self):
"""加载配置文件"""
......@@ -247,22 +228,12 @@ class GlobalDetectionThread:
self.default_batch_size = config.get('default_batch_size', 4)
self.max_wait_time = config.get('max_batch_wait_time', 0.05)
print(f"📋 [全局检测线程] 配置加载成功:")
print(f" - 检测帧率: {self.detection_frame_rate}")
print(f" - 批处理: {self.batch_processing_enabled}")
print(f" - 批大小: {self.default_batch_size}")
print(f" - 最大等待: {self.max_wait_time}s")
else:
print(f"⚠️ [全局检测线程] 配置文件不存在,使用默认配置: {config_file}")
except Exception as e:
print(f"❌ [全局检测线程] 配置加载失败: {e}")
pass
def _initialize_components(self):
"""初始化核心组件"""
try:
print("🔧 [全局检测线程] 初始化核心组件...")
# 模型池管理器(真实实现)
from ..model_pool_manager import ModelPoolManager
self.model_pool_manager = ModelPoolManager()
......@@ -283,15 +254,11 @@ class GlobalDetectionThread:
from ..result_distributor import ResultDistributor
self.result_distributor = ResultDistributor()
print("✅ [全局检测线程] 核心组件初始化完成")
except Exception as e:
print(f"❌ [全局检测线程] 组件初始化失败: {e}")
raise
def _main_loop(self):
"""主循环 - 全局检测线程的核心逻辑"""
print("🔄 [全局检测线程] 主循环开始")
frame_interval = 1.0 / self.detection_frame_rate if self.detection_frame_rate > 0 else 0.2
......@@ -331,12 +298,9 @@ class GlobalDetectionThread:
time.sleep(sleep_time)
except Exception as e:
print(f"❌ [全局检测线程] 主循环异常: {e}")
import traceback
traceback.print_exc()
time.sleep(0.1)
print("🔄 [全局检测线程] 主循环结束")
def _collect_frames(self) -> Dict[str, Any]:
"""收集各通道的帧数据"""
......@@ -347,7 +311,6 @@ class GlobalDetectionThread:
return collected_data
except Exception as e:
print(f"❌ [全局检测线程] 帧收集失败: {e}")
return {
'model_groups': {},
'total_frames': 0,
......@@ -378,7 +341,6 @@ class GlobalDetectionThread:
)
except Exception as e:
print(f"❌ [全局检测线程] 结果分发失败: {e}")
import traceback
traceback.print_exc()
......@@ -400,23 +362,15 @@ class GlobalDetectionThread:
channel_id: 通道ID
"""
try:
print(f"🔄 [全局检测线程] 验证通道 {channel_id} 的标注配置...")
# 使用模型池管理器的方法验证配置
annotation_config = self.model_pool_manager.get_channel_annotation_config(channel_id)
if not annotation_config:
print(f"⚠️ [全局检测线程] 通道 {channel_id} 的标注配置不存在或加载失败")
return False
print(f"✅ [全局检测线程] 通道 {channel_id} 的标注配置验证通过")
print(f" - 检测区域数量: {len(annotation_config.get('boxes', []))}")
print(f" - 区域高度: {annotation_config.get('actual_heights', [])}")
return True
except Exception as e:
print(f"❌ [全局检测线程] 验证标注配置失败: {e}")
import traceback
traceback.print_exc()
return False
......@@ -426,7 +380,6 @@ class GlobalDetectionThread:
try:
# 清理核心组件
if self.model_pool_manager and hasattr(self.model_pool_manager, 'cleanup'):
print("🧹 [全局检测线程] 清理模型池管理器...")
self.model_pool_manager.cleanup()
# 清理通道信息
......@@ -434,10 +387,8 @@ class GlobalDetectionThread:
self.channel_contexts.clear()
self.channel_callbacks.clear()
print("🧹 [全局检测线程] 资源清理完成")
except Exception as e:
print(f"❌ [全局检测线程] 资源清理失败: {e}")
pass
def get_stats(self) -> Dict[str, Any]:
"""获取性能统计信息"""
......
......@@ -90,8 +90,6 @@ class StorageThread:
csv_file = open(csv_filepath, 'a', encoding='utf-8', buffering=8192) # 8KB缓冲
csv_files[area_idx] = csv_file
csv_writers[area_idx] = csv_file
print(f" - 区域{area_idx+1}({area_name}): {csv_filename}")
# 存储线程不受 save_data_rate 限制,全速消费队列,避免数据丢失
# save_data_rate 仅用于配置文件记录,实际存储线程会保存所有检测结果
......@@ -216,7 +214,6 @@ class StorageThread:
config_file = os.path.join(project_root, 'database', 'config', 'channel_config.yaml')
if not os.path.exists(config_file):
print(f"⚠️ 配置文件不存在: {config_file}")
return None
with open(config_file, 'r', encoding='utf-8') as f:
......@@ -227,7 +224,6 @@ class StorageThread:
return None
except Exception as e:
print(f"❌ 加载通道配置失败: {e}")
import traceback
traceback.print_exc()
return None
......@@ -277,42 +273,38 @@ class StorageThread:
def _get_area_names(channel_id: str, channel_config: dict):
"""获取区域名称列表
从 annotation_result.yaml 读取区域名称
Args:
channel_id: 通道ID
channel_config: 通道配置字典
channel_config: 通道配置字典(保留参数以保持接口兼容)
Returns:
dict: {区域索引: 区域名称}
"""
area_names = {}
if channel_config:
areas = channel_config.get('general', {}).get('areas', {})
area_count = channel_config.get('general', {}).get('area_count', 0)
# 获取通道名称(用于生成默认区域名称)
channel_name = StorageThread._get_channel_name(channel_id, channel_config)
try:
project_root = StorageThread._get_project_root()
annotation_file = os.path.join(project_root, 'database', 'config', 'annotation_result.yaml')
for i in range(area_count):
area_key = f'area_{i+1}'
area_name = areas.get(area_key, '')
# 如果没有区域名称,使用与标注界面相同的默认生成逻辑
if not area_name:
if channel_name:
area_name = f"{channel_name}_区域{i+1}"
else:
area_name = f"区域{i+1}"
if os.path.exists(annotation_file):
with open(annotation_file, 'r', encoding='utf-8') as f:
annotation_data = yaml.safe_load(f)
area_names[i] = area_name
# 如果没有配置区域,使用默认值(保持向后兼容)
if not area_names:
channel_name = StorageThread._get_channel_name(channel_id, channel_config)
if channel_name:
area_names = {0: f"{channel_name}_区域1"}
else:
area_names = {0: "区域1"}
if annotation_data and channel_id in annotation_data:
areas_config = annotation_data[channel_id].get('areas', {})
# 从标注结果读取区域名称
for area_key, area_info in areas_config.items():
# area_key 格式: 'area_1', 'area_2', ...
area_idx = int(area_key.split('_')[1]) - 1 # 转换为0索引
area_name = area_info.get('name', '')
if area_name:
area_names[area_idx] = area_name
except Exception as e:
pass
return area_names
......@@ -328,7 +320,6 @@ class StorageThread:
str: 任务路径,如果未设置则返回None
"""
if not main_window:
print(f"⚠️ [存储线程-{channel_id}] 主窗口实例为空,无法获取通道任务路径")
return None
try:
......@@ -341,25 +332,19 @@ class StorageThread:
mission_label = getattr(main_window, mission_var_name)
task_folder_name = mission_label.text()
print(f"📁 [存储线程-{channel_id}] 从 {mission_var_name} 读取任务: {task_folder_name}")
# 检查任务是否有效
if not task_folder_name or task_folder_name.strip() == "" or task_folder_name == "未分配任务":
print(f"⚠️ [存储线程-{channel_id}] 通道未分配任务,跳过存储")
return None
# 构建完整的任务路径
project_root = StorageThread._get_project_root()
mission_path = os.path.join(project_root, 'database', 'mission_result', task_folder_name.strip())
print(f"✅ [存储线程-{channel_id}] 任务路径: {mission_path}")
return mission_path
else:
print(f"⚠️ [存储线程-{channel_id}] 主窗口中未找到变量: {mission_var_name}")
return None
except Exception as e:
print(f"❌ [存储线程-{channel_id}] 获取通道任务路径失败: {e}")
import traceback
traceback.print_exc()
return None
......
......@@ -140,7 +140,6 @@ class ViewHandler:
"""切换到曲线模式:根据检测线程状态选择合适的子布局"""
# 🔥 检查检测线程状态,决定使用哪种子布局
detection_running = self._getCurrentDetectionState()
print(f"🔄 [曲线模式] 检测线程状态: {detection_running}")
# 根据检测线程状态切换到对应的曲线子布局
self._switchCurveSubLayout(detection_running)
......@@ -155,20 +154,15 @@ class ViewHandler:
target_channel_widgets = self.history_channel_widgets_for_curve
layout_description = "历史回放模式"
print(f"📋 [曲线模式] 使用{layout_description}")
# 🔥 根据检测线程状态选择要显示的面板类型
if detection_running:
# 实时检测模式:使用通道面板(ChannelPanel)
panels_to_use = self.channelPanels
print(f"📋 [曲线模式] 使用通道面板(ChannelPanel)")
else:
# 历史回放模式:使用历史视频面板(HistoryVideoPanel)
if hasattr(self, 'historyVideoPanels'):
panels_to_use = self.historyVideoPanels
print(f"📋 [曲线模式] 使用历史视频面板(HistoryVideoPanel)")
else:
print(f"⚠️ [曲线模式] 未找到历史视频面板,回退到通道面板")
panels_to_use = self.channelPanels
# 🔥 先隐藏所有wrapper
......@@ -206,13 +200,6 @@ class ViewHandler:
# 🔥 强制更新布局
wrapper.updateGeometry()
panel.updateGeometry()
# 🔥 调试信息
print(f" ✅ 已将 {panel.objectName()} 添加到 wrapper[{i}]")
print(f" - 面板尺寸: {panel.size().width()}x{panel.size().height()}")
print(f" - wrapper尺寸: {wrapper.size().width()}x{wrapper.size().height()}")
print(f" - 面板可见: {panel.isVisible()}")
print(f" - wrapper可见: {wrapper.isVisible()}")
# 先设置模式为曲线模式(_video_layout_mode = 1)
self._video_layout_mode = 1
......@@ -244,18 +231,15 @@ class ViewHandler:
selected_channels = self._getTaskChannels(current_mission)
if hasattr(self, '_updateCurveChannelDisplay'):
self._updateCurveChannelDisplay(selected_channels)
print(f"🔄 [曲线模式] 实时检测模式:已根据任务 {current_mission} 更新通道显示: {selected_channels}")
else:
# 没有选择任务,隐藏所有通道
if hasattr(self, '_updateCurveChannelDisplay'):
self._updateCurveChannelDisplay([])
print(f"🔄 [曲线模式] 实时检测模式:未选择任务,隐藏所有通道")
else:
# 🔥 历史回放模式:显示所有历史视频面板
if hasattr(self, '_updateCurveChannelDisplay'):
all_channels = ['通道1', '通道2', '通道3', '通道4']
self._updateCurveChannelDisplay(all_channels) # 显示所有4个历史视频面板
print(f"🔄 [曲线模式] 历史回放模式:显示所有历史视频面板")
# 强制刷新整个布局
self.videoLayoutStack.currentWidget().updateGeometry()
......@@ -269,37 +253,15 @@ class ViewHandler:
def _switchToDefaultLayout(self):
"""切换到默认布局(实时检测模式)"""
print(f"\n{'='*60}")
print(f"[布局切换] ========== 切换到默认布局(实时检测) ==========")
print(f"{'='*60}")
# 检查必要的属性
print(f"[布局切换] 检查属性:")
print(f" - hasattr videoLayoutStack: {hasattr(self, 'videoLayoutStack')}")
print(f" - hasattr channelPanels: {hasattr(self, 'channelPanels')}")
print(f" - hasattr default_channel_container: {hasattr(self, 'default_channel_container')}")
if hasattr(self, 'videoLayoutStack'):
print(f" - videoLayoutStack 当前索引: {self.videoLayoutStack.currentIndex()}")
print(f" - videoLayoutStack 子控件数量: {self.videoLayoutStack.count()}")
for i in range(self.videoLayoutStack.count()):
widget = self.videoLayoutStack.widget(i)
print(f" 索引{i}: {widget} (可见: {widget.isVisible() if widget else 'None'})")
# 🔥 停止所有曲线线程(切换回默认布局时)
self._stopAllCurveThreads()
print(f"[布局切换] 已停止所有曲线线程")
# 🔥 切换曲线绘制模式为实时模式
if hasattr(self, 'curvePanelHandler'):
self.curvePanelHandler.setCurveLoadMode('realtime')
print(f"[布局切换] 曲线绘制模式已切换为: realtime")
# 将通道面板移回默认布局
print(f"[布局切换] 移动通道面板到默认位置...")
if hasattr(self, 'channelPanels'):
print(f" - 通道面板数量: {len(self.channelPanels)}")
for i, channel_panel in enumerate(self.channelPanels):
if i < len(self.default_channel_positions):
# 从wrapper布局中移除
......@@ -307,30 +269,20 @@ class ViewHandler:
wrapper_layout = wrapper.layout()
if wrapper_layout and wrapper_layout.indexOf(channel_panel) >= 0:
wrapper_layout.removeWidget(channel_panel)
print(f" - 通道{i+1}: 从wrapper移除")
# 重设父容器和位置
channel_panel.setParent(self.default_channel_container)
x, y = self.default_channel_positions[i]
channel_panel.move(x, y)
channel_panel.show()
print(f" - 通道{i+1}: 移动到位置({x}, {y}), 可见性: {channel_panel.isVisible()}")
# 设置模式为默认模式(_video_layout_mode = 0)
self._video_layout_mode = 0
print(f"[布局切换] 设置模式: _video_layout_mode = 0")
# 切换布局
print(f"[布局切换] 切换 videoLayoutStack 到索引 0...")
self.videoLayoutStack.setCurrentIndex(0)
print(f"[布局切换] 切换后索引: {self.videoLayoutStack.currentIndex()}")
current_widget = self.videoLayoutStack.currentWidget()
print(f"[布局切换] 当前控件: {current_widget}")
if current_widget:
print(f" - 可见性: {current_widget.isVisible()}")
print(f" - 大小: {current_widget.size()}")
print(f" - 子控件数量: {len(current_widget.children())}")
self.statusBar().showMessage(self.tr("当前页面: 实时检测管理"))
......@@ -349,8 +301,6 @@ class ViewHandler:
self.videoLayoutStack.currentWidget().updateGeometry()
from qtpy.QtWidgets import QApplication
QApplication.processEvents()
print(f"[布局切换] ========== 切换完成 ==========\n")
def switchToRealTimeDetectionPage(self):
"""切换到实时检测页面(兼容性方法,委托给 _switchToDefaultLayout)"""
......@@ -372,7 +322,6 @@ class ViewHandler:
mode_text = "实时检测"
mode_style = "font-weight: bold; padding: 2px 8px;"
curve_mode = 'realtime'
print(f"🔄 [曲线子布局] 检测线程运行中,切换到{layout_name}")
else:
# 切换到历史回放布局(索引1)
......@@ -381,13 +330,11 @@ class ViewHandler:
mode_text = "历史回放"
mode_style = "font-weight: bold; padding: 2px 8px;"
curve_mode = 'history'
print(f"🔄 [曲线子布局] 检测线程停止,切换到{layout_name}")
# 🔥 同步切换曲线绘制模式
if hasattr(self, 'curvePanelHandler'):
self.curvePanelHandler.setCurveLoadMode(curve_mode)
print(f"🔄 [曲线绘制模式] 已切换到: {curve_mode}")
# 更新模式标签
if hasattr(self, 'curvePanel') and hasattr(self.curvePanel, 'mode_label'):
......@@ -401,22 +348,16 @@ class ViewHandler:
FontManager.applyToWidget(self.curvePanel.mode_label)
except ImportError:
pass
print(f"✅ [模式标签] 已更新为: {mode_text}")
# 执行布局切换
if self.curveLayoutStack.currentIndex() != target_index:
self.curveLayoutStack.setCurrentIndex(target_index)
self._curve_sub_layout_mode = target_index
print(f"✅ [曲线子布局] 已切换到{layout_name}(索引{target_index})")
else:
print(f"📋 [曲线子布局] 已经是{layout_name},无需切换")
# 🔥 切换模式后,重新应用通道筛选逻辑
if hasattr(self, 'curvemission') and hasattr(self, '_onCurveMissionChanged'):
current_mission = self.curvemission.currentText()
if current_mission and current_mission != "请选择任务":
print(f"🔄 [通道筛选] 模式切换后,重新筛选通道: {current_mission}")
self._onCurveMissionChanged(current_mission)
......
......@@ -443,13 +443,11 @@ class ChannelPanel(QtWidgets.QWidget):
# 只显示文件夹名称
text = task_folder_name.strip()
self.taskLabel.setText(text)
print(f"[ChannelPanel.setTaskInfo] 显示任务信息: {text}")
# 有任务时启用面板
self._setDisabled(False)
else:
# 没有任务信息时显示未分配任务
self.taskLabel.setText("未分配任务")
print(f"[ChannelPanel.setTaskInfo] 任务为空,显示'未分配任务',输入参数: task_folder_name={task_folder_name}")
# 无任务时禁用面板
self._setDisabled(True)
......@@ -460,7 +458,6 @@ class ChannelPanel(QtWidgets.QWidget):
def clearTaskInfo(self):
"""清空任务信息显示"""
self.taskLabel.setText("未分配任务")
print(f"ℹ️ [ChannelPanel.clearTaskInfo] 清空任务信息,显示'未分配任务'")
# 清空任务时禁用面板
self._setDisabled(True)
self.taskLabel.adjustSize()
......@@ -505,7 +502,6 @@ class ChannelPanel(QtWidgets.QWidget):
background-color: rgba(0, 0, 0, 0.5);
}
""")
print(f"🚫 [ChannelPanel] 面板已禁用: {self._title} (所有按钮已禁用)")
else:
# 启用所有按钮
if hasattr(self, 'btnToggleConnect'):
......@@ -519,7 +515,6 @@ class ChannelPanel(QtWidgets.QWidget):
# 移除遮罩效果
self.setStyleSheet("")
print(f"[ChannelPanel] 面板已启用: {self._title} (所有按钮已启用)")
def mousePressEvent(self, event):
"""鼠标点击事件 - 禁用状态下显示提示"""
......@@ -759,23 +754,21 @@ if __name__ == "__main__":
# 连接信号用于测试
def on_channel_connected(cam_id):
print(f" 打开通道: {cam_id}")
# 模拟连接成功后切换状态
channel_panel.setConnected(True)
def on_channel_disconnected(cam_id):
print(f"̸ 断开通道: {cam_id}")
# 模拟断开成功后切换状态
channel_panel.setConnected(False)
def on_curve_clicked():
print(f" 曲线按钮被点击")
pass
def on_amplify_clicked():
print(f" 放大按钮被点击")
pass
def on_edit_clicked(cam_id, data):
print(f" 通道设置: {cam_id}")
pass
channel_panel.channelConnected.connect(on_channel_connected)
channel_panel.channelDisconnected.connect(on_channel_disconnected)
......
......@@ -96,9 +96,7 @@ class MissionPanel(QtWidgets.QWidget):
self._connectSignals()
# 🔥 暂时禁用全局字体管理器,测试是否解决重复显示问题
print(f"🔍 [调试] 跳过全局字体管理器应用到任务面板")
# FontManager.applyToWidgetRecursive(self)
print(f"🔍 [调试] 全局字体管理器已跳过")
# 自动应用默认配置
self._applyDefaultConfig()
......@@ -657,15 +655,12 @@ class MissionPanel(QtWidgets.QWidget):
"""
# 检查行索引是否有效
if row < 0 or row >= len(self._all_rows_data):
print(f"⚠️ [setCellTextColor] 行索引无效: row={row}, 总行数={len(self._all_rows_data)}")
return
# 计算在当前页面中的行索引
start_idx = (self._current_page - 1) * self._page_size
end_idx = start_idx + self._page_size
print(f"🔍 [setCellTextColor] 行{row} 列{col}, 当前页={self._current_page}, 页面范围=[{start_idx}, {end_idx})")
# 检查该行是否在当前页面中
if start_idx <= row < end_idx:
table_row = row - start_idx
......@@ -675,11 +670,6 @@ class MissionPanel(QtWidgets.QWidget):
item.setForeground(QtGui.QColor(color))
else:
item.setForeground(color)
print(f"✅ [setCellTextColor] 已设置 行{row}(表格行{table_row}) 列{col} 颜色={color}, 文本={item.text()}")
else:
print(f"⚠️ [setCellTextColor] 单元格为空: 行{row}(表格行{table_row}) 列{col}")
else:
print(f"⚠️ [setCellTextColor] 行{row}不在当前页面中")
def _addRowToTable(self, row_data, user_data=None, button_callback=None):
"""
......@@ -713,13 +703,9 @@ class MissionPanel(QtWidgets.QWidget):
# 🔥 通道列始终设置为灰色字体
if self.CHANNEL_START_COLUMN <= col_index < self.CHANNEL_START_COLUMN + self.CHANNEL_COUNT:
item.setForeground(QtGui.QColor(128, 128, 128)) # 设置灰色文字
print(f"[调试] 设置通道列灰色字体: 行={row_index}, 列={col_index}, 值='{value}'")
# 🔥 如果是未配置状态且不是通道列,设置灰色前景色
elif is_unconfigured:
item.setForeground(QtGui.QColor(128, 128, 128)) # 设置灰色文字
print(f"[调试] 设置未配置状态灰色QTableWidgetItem: 行={row_index}, 列={col_index}, 值='{value}'")
else:
print(f"[调试] 设置普通QTableWidgetItem: 行={row_index}, 列={col_index}, 值='{value}'")
# 设置到表格
self.table.setItem(row_index, col_index, item)
......@@ -737,7 +723,6 @@ class MissionPanel(QtWidgets.QWidget):
row_index: 行索引
row_data: 行数据列表
"""
print(f"[调试] _setRowDefaultColor 被调用: 行={row_index}, 数据={row_data}")
# 设置所有列的字体颜色为默认色(黑色)
for col_index in range(len(row_data)):
......@@ -748,7 +733,6 @@ class MissionPanel(QtWidgets.QWidget):
item = self.table.item(row_index, col_index)
if item:
item.setForeground(QtGui.QColor(0, 0, 0)) # 设置黑色文字
print(f"[调试] 设置默认颜色QTableWidgetItem: 行={row_index}, 列={col_index}")
def _setRowGrayColor(self, row_index, row_data):
"""
......@@ -758,7 +742,6 @@ class MissionPanel(QtWidgets.QWidget):
row_index: 行索引
row_data: 行数据列表
"""
print(f"[调试] _setRowGrayColor 被调用: 行={row_index}, 数据={row_data}")
# 设置所有列的字体颜色为灰色
for col_index in range(len(row_data)):
......@@ -769,24 +752,12 @@ class MissionPanel(QtWidgets.QWidget):
item = self.table.item(row_index, col_index)
if item:
item.setForeground(QtGui.QColor(128, 128, 128)) # 设置灰色文字
print(f"[调试] 设置灰色QTableWidgetItem: 行={row_index}, 列={col_index}")
def _testFontException(self):
"""
测试字体例外机制是否正常工作
"""
print(f"🔍 [测试] 开始测试字体例外机制")
print(f"🔍 [测试] 当前例外控件总数: {len(FontManager.FONT_EXCEPTIONS)}")
# 遍历表格中的所有控件
for row in range(self.table.rowCount()):
for col in range(self.table.columnCount()):
widget = self.table.cellWidget(row, col)
if widget and isinstance(widget, QtWidgets.QLabel):
is_exception = FontManager.isFontException(widget)
style = widget.styleSheet()
print(f"🔍 [测试] 行{row}列{col}: 是否例外={is_exception}, 样式='{style}'")
"""
def updateRow(self, row_index, row_data):
......@@ -1122,7 +1093,6 @@ class MissionPanel(QtWidgets.QWidget):
"""单元格被双击 - 恢复任务分配功能"""
if item:
row = item.row()
print(f"🔍 [调试] 双击事件: 行={row}, 准备分配任务")
# 发送行选中信号
self.itemSelected.emit(row)
......@@ -1130,12 +1100,9 @@ class MissionPanel(QtWidgets.QWidget):
# 获取任务信息并发送任务选中信号给handler
user_data = self.getUserData(row)
if user_data:
print(f"🔍 [调试] 发送任务选中信号: {user_data}")
# 🔥 保存当前双击的行索引,等待handler确认后再置黑
self._pending_highlight_row = row
self.taskSelected.emit(user_data)
else:
print(f"🔍 [调试] 警告:行{row}没有用户数据")
def _assignTaskToChannels(self, row):
"""
......@@ -1152,7 +1119,6 @@ class MissionPanel(QtWidgets.QWidget):
if user_data:
# 发送任务选中信号给handler
self.taskSelected.emit(user_data)
print(f"✅ [任务分配] 手动分配任务: {user_data}")
def confirmTaskAssignment(self):
"""
......@@ -1163,7 +1129,6 @@ class MissionPanel(QtWidgets.QWidget):
if self._pending_highlight_row is not None:
self._highlightSelectedRow(self._pending_highlight_row)
self._pending_highlight_row = None
print(f"✅ [任务分配] 已确认并高亮任务行")
def cancelTaskAssignment(self):
"""
......@@ -1172,7 +1137,6 @@ class MissionPanel(QtWidgets.QWidget):
当用户在确认对话框中点击"取消"后,handler调用此方法来清除待高亮状态
"""
if self._pending_highlight_row is not None:
print(f"❌ [任务分配] 用户取消,不高亮行 {self._pending_highlight_row}")
self._pending_highlight_row = None
def _highlightSelectedRow(self, selected_row):
......@@ -1190,10 +1154,8 @@ class MissionPanel(QtWidgets.QWidget):
item.setForeground(QtGui.QColor(0, 0, 0)) # 黑色文字
# 不设置背景色,保持原有背景
print(f"✅ [高亮] 已将选中行文字颜色置黑: {selected_row}")
except Exception as e:
print(f"❌ [高亮] 高亮行失败: {e}")
pass
def _onCellChanged(self, row, column):
"""单元格内容改变"""
......@@ -1538,11 +1500,32 @@ class MissionPanel(QtWidgets.QWidget):
def addTaskRow(self, task_info):
"""添加任务行(由handler调用)"""
# 获取选中的通道列表
selected_channels = task_info.get('selected_channels', [])
# 初始化4个通道列的数据(默认为空)
channel_data = ['', '', '', '']
# 将选中的通道填充到对应的列
for channel in selected_channels:
if channel == '通道1':
channel_data[0] = '通道1'
elif channel == '通道2':
channel_data[1] = '通道2'
elif channel == '通道3':
channel_data[2] = '通道3'
elif channel == '通道4':
channel_data[3] = '通道4'
# 构建行数据:任务编号、任务名称、状态、通道1、通道2、通道3、通道4、曲线
row_data = [
task_info.get('task_id', ''),
task_info.get('task_name', ''),
task_info.get('status', '待配置'),
', '.join(task_info.get('selected_channels', [])),
channel_data[0], # 通道1列
channel_data[1], # 通道2列
channel_data[2], # 通道3列
channel_data[3], # 通道4列
'' # 曲线列(按钮会自动添加)
]
self.addRow(row_data, task_info)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment