Commit 0e36f2c7 by Yuhaibo

1

parent 78c7fd7b
......@@ -954,12 +954,10 @@ class MainWindow(
def _onCurveMissionChanged(self, mission_name):
"""曲线任务选择变化(基于CSV文件动态显示)"""
if not mission_name or mission_name == "请选择任务":
print(f"[曲线布局] 未选择任务,隐藏所有通道容器")
self._updateCurveChannelDisplay([])
return
# 🔥 重新检查检测状态并切换布局
print(f"\n🔄 [任务切换] 任务已切换到: {mission_name},重新检查检测状态...")
detection_running = False
if hasattr(self, '_switchCurveSubLayout') and hasattr(self, '_getCurrentDetectionState'):
detection_running = self._getCurrentDetectionState()
......@@ -969,11 +967,9 @@ class MainWindow(
if detection_running:
# 🔥 实时检测模式:只显示任务配置中使用的通道
selected_channels = self._getTaskChannels(mission_name)
print(f"📊 [曲线布局-实时模式] 任务 {mission_name},显示任务使用的通道: {selected_channels}")
else:
# 🔥 历史回放模式:显示所有通道容器
selected_channels = ['通道1', '通道2', '通道3', '通道4']
print(f"📊 [曲线布局-历史模式] 任务 {mission_name},显示所有通道容器")
self._updateCurveChannelDisplay(selected_channels)
......@@ -1015,7 +1011,7 @@ class MainWindow(
return []
# 调试:打印配置文件的所有键
print(f" [通道筛选] 配置文件键: {list(task_config.keys())}")
# 从配置中提取使用的通道
# 配置格式可能是:selected_channels: ['通道2', '通道3'] 或 channels: ['channel1', 'channel2']
......@@ -1027,7 +1023,6 @@ class MainWindow(
channel_list = task_config['selected_channels']
if isinstance(channel_list, list):
used_channels = [ch for ch in channel_list if isinstance(ch, str) and '通道' in ch]
print(f" [通道筛选] 从 selected_channels 读取: {used_channels}")
# 尝试其他可能的配置键名
elif 'channels' in task_config:
......
channel1:
annotation_count: 1
annotation_count: 2
areas:
area_1:
height: 20mm
name: 通道1_区域1
area_2:
height: 20mm
name: 通道1_区域2
boxes:
- - 715
- 629
- 416
- - 520
- 576
- 288
- - 1289
- 645
- 352
fixed_bottoms:
- 795
- 691
- 785
fixed_tops:
- 462
last_updated: '2025-11-29 13:46:20'
- 460
- 504
last_updated: '2025-11-29 14:57:04'
channel2:
annotation_count: 1
areas:
......
......@@ -18,22 +18,22 @@ channels:
channel2:
general:
task_id: '1'
task_name: '2'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_2
task_name: '1'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
channel3:
general:
task_id: '1'
task_name: '222'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_222
task_name: '1'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
channel4:
general:
task_id: '1'
task_name: '222'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_222
task_name: '1'
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
channel1:
general:
task_id: 2 去
task_name:
task_id: '1'
task_name: '1'
area_count: 0
safe_low: 2.0mm
safe_high: 10.0mm
......@@ -41,14 +41,11 @@ channel1:
video_format: AVI
push_address: ''
video_path: ''
save_liquid_data_path: D:\restructure\liquid_level_line_detection_system\database\mission_result\2
去_去
save_liquid_data_path: d:\restructure\liquid_level_line_detection_system\database\mission_result\1_1
areas:
area_1: 通道1_区域1
area_2: 通道1_区域2
area_heights:
area_1: 20mm
area_2: 20mm
model:
model_path: d:\restructure\liquid_level_line_detection_system\database\model\detection_model\5\best.dat
channel_1:
......
2025-11-29-11:13:54.674 0.0
2025-11-29-11:13:54.674 0.0
......@@ -14657,3 +14657,269 @@
2025-11-29-13:52:30.872 0.0
2025-11-29-13:52:31.084 16.0
2025-11-29-13:52:31.354 0.0
2025-11-29-14:31:36.260 0.0
2025-11-29-14:31:36.295 0.0
2025-11-29-14:31:36.487 0.0
2025-11-29-14:31:36.696 0.0
2025-11-29-14:31:36.899 0.0
2025-11-29-14:31:37.095 0.0
2025-11-29-14:31:37.294 0.0
2025-11-29-14:31:37.497 0.0
2025-11-29-14:31:37.697 0.0
2025-11-29-14:31:37.905 0.0
2025-11-29-14:31:38.107 0.0
2025-11-29-14:31:38.314 0.0
2025-11-29-14:31:38.511 0.0
2025-11-29-14:31:38.740 0.0
2025-11-29-14:31:38.934 0.0
2025-11-29-14:31:39.133 0.0
2025-11-29-14:31:39.338 0.0
2025-11-29-14:31:39.563 0.0
2025-11-29-14:31:39.753 0.0
2025-11-29-14:31:39.969 0.0
2025-11-29-14:31:40.176 0.0
2025-11-29-14:31:40.380 0.0
2025-11-29-14:31:40.576 0.0
2025-11-29-14:31:40.793 0.0
2025-11-29-14:31:41.002 0.0
2025-11-29-14:31:41.185 0.0
2025-11-29-14:31:41.399 0.0
2025-11-29-14:31:41.607 0.0
2025-11-29-14:31:41.805 0.0
2025-11-29-14:31:42.016 0.0
2025-11-29-14:31:42.244 0.0
2025-11-29-14:31:42.434 0.0
2025-11-29-14:31:42.639 0.0
2025-11-29-14:31:42.855 0.0
2025-11-29-14:31:43.058 0.0
2025-11-29-14:31:43.275 0.0
2025-11-29-14:31:43.468 0.0
2025-11-29-14:31:43.681 0.0
2025-11-29-14:31:43.898 0.0
2025-11-29-14:31:44.100 0.0
2025-11-29-14:31:44.314 0.0
2025-11-29-14:31:44.514 0.0
2025-11-29-14:31:44.710 0.0
2025-11-29-14:31:44.923 0.0
2025-11-29-14:31:45.159 0.0
2025-11-29-14:31:45.368 0.0
2025-11-29-14:31:45.567 0.0
2025-11-29-14:31:45.761 0.0
2025-11-29-14:31:45.982 0.0
2025-11-29-14:31:46.179 0.0
2025-11-29-14:31:46.393 0.0
2025-11-29-14:31:46.589 0.0
2025-11-29-14:31:46.804 0.0
2025-11-29-14:31:46.999 0.0
2025-11-29-14:31:47.204 0.0
2025-11-29-14:31:47.425 0.0
2025-11-29-14:31:47.613 0.0
2025-11-29-14:31:47.827 0.0
2025-11-29-14:31:48.023 0.0
2025-11-29-14:31:48.225 0.0
2025-11-29-14:31:48.419 0.0
2025-11-29-14:31:48.625 0.0
2025-11-29-14:31:48.851 0.0
2025-11-29-14:31:49.045 0.0
2025-11-29-14:31:49.271 0.0
2025-11-29-14:31:49.462 0.0
2025-11-29-14:31:49.659 0.0
2025-11-29-14:31:49.865 0.0
2025-11-29-14:31:50.084 0.0
2025-11-29-14:31:50.270 0.0
2025-11-29-14:31:50.482 0.0
2025-11-29-14:31:50.677 0.0
2025-11-29-14:31:50.899 0.0
2025-11-29-14:31:51.088 0.0
2025-11-29-14:31:51.306 0.0
2025-11-29-14:31:51.513 0.0
2025-11-29-14:31:51.699 0.0
2025-11-29-14:31:51.908 0.0
2025-11-29-14:31:52.104 0.0
2025-11-29-14:31:52.303 0.0
2025-11-29-14:31:52.518 0.0
2025-11-29-14:31:52.713 0.0
2025-11-29-14:31:52.939 0.0
2025-11-29-14:31:53.128 0.0
2025-11-29-14:31:53.327 0.0
2025-11-29-14:31:53.529 0.0
2025-11-29-14:31:53.735 0.0
2025-11-29-14:31:53.939 0.0
2025-11-29-14:31:54.141 0.0
2025-11-29-14:31:54.360 0.0
2025-11-29-14:31:54.579 0.0
2025-11-29-14:31:54.780 0.0
2025-11-29-14:31:54.984 0.0
2025-11-29-14:31:55.188 0.0
2025-11-29-14:31:55.397 0.0
2025-11-29-14:31:55.601 0.0
2025-11-29-14:31:55.791 0.0
2025-11-29-14:31:56.001 0.0
2025-11-29-14:31:56.197 0.0
2025-11-29-14:31:56.418 0.0
2025-11-29-14:31:56.617 0.0
2025-11-29-14:31:56.822 0.0
2025-11-29-14:31:57.025 0.0
2025-11-29-14:31:57.226 0.0
2025-11-29-14:31:57.423 0.0
2025-11-29-14:31:57.652 0.0
2025-11-29-14:31:57.859 0.0
2025-11-29-14:31:58.068 0.0
2025-11-29-14:31:58.288 0.0
2025-11-29-14:31:58.481 0.0
2025-11-29-14:31:58.699 0.0
2025-11-29-14:31:58.889 0.0
2025-11-29-14:31:59.120 0.0
2025-11-29-14:31:59.310 0.0
2025-11-29-14:31:59.508 0.0
2025-11-29-14:31:59.721 0.0
2025-11-29-14:31:59.913 0.0
2025-11-29-14:32:00.133 0.0
2025-11-29-14:32:00.329 0.0
2025-11-29-14:32:00.545 0.0
2025-11-29-14:32:00.742 0.0
2025-11-29-14:32:00.970 0.0
2025-11-29-14:32:01.147 0.0
2025-11-29-14:32:01.366 0.0
2025-11-29-14:32:01.566 0.0
2025-11-29-14:32:01.765 0.0
2025-11-29-14:32:01.985 0.0
2025-11-29-14:32:02.178 0.0
2025-11-29-14:32:02.385 0.0
2025-11-29-14:32:02.577 0.0
2025-11-29-14:32:02.784 0.0
2025-11-29-14:32:02.988 0.0
2025-11-29-14:32:03.217 0.0
2025-11-29-14:32:03.405 0.0
2025-11-29-14:32:03.614 0.0
2025-11-29-14:32:03.821 0.0
2025-11-29-14:32:04.024 0.0
2025-11-29-14:32:04.230 0.0
2025-11-29-14:32:04.435 0.0
2025-11-29-14:32:04.659 0.0
2025-11-29-14:32:04.856 0.0
2025-11-29-14:32:05.070 0.0
2025-11-29-14:32:05.285 0.0
2025-11-29-14:32:05.465 0.0
2025-11-29-14:32:05.669 0.0
2025-11-29-14:32:05.884 0.0
2025-11-29-14:32:06.082 0.0
2025-11-29-14:32:06.286 0.0
2025-11-29-14:32:06.497 0.0
2025-11-29-14:32:06.705 0.0
2025-11-29-14:32:06.913 0.0
2025-11-29-14:32:07.124 0.0
2025-11-29-14:32:07.309 0.0
2025-11-29-14:32:07.522 0.0
2025-11-29-14:32:07.721 0.0
2025-11-29-14:32:07.923 0.0
2025-11-29-14:32:08.132 0.0
2025-11-29-14:32:08.337 0.0
2025-11-29-14:32:08.536 0.0
2025-11-29-14:32:08.761 0.0
2025-11-29-14:32:08.952 0.0
2025-11-29-14:32:09.156 0.0
2025-11-29-14:32:09.365 0.0
2025-11-29-14:32:09.577 0.0
2025-11-29-14:32:09.763 0.0
2025-11-29-14:32:09.975 0.0
2025-11-29-14:32:10.173 0.0
2025-11-29-14:32:10.390 0.0
2025-11-29-14:32:10.674 16.0
2025-11-29-14:32:10.806 0.0
2025-11-29-14:32:10.997 0.0
2025-11-29-14:32:11.221 0.0
2025-11-29-14:32:11.424 0.0
2025-11-29-14:32:11.674 0.0
2025-11-29-14:32:11.864 0.0
2025-11-29-14:32:12.064 0.0
2025-11-29-14:32:12.274 0.0
2025-11-29-14:32:12.474 0.0
2025-11-29-14:32:12.677 0.0
2025-11-29-14:32:12.884 0.0
2025-11-29-14:32:13.087 0.0
2025-11-29-14:32:13.301 0.0
2025-11-29-14:32:13.541 0.0
2025-11-29-14:32:13.725 0.0
2025-11-29-14:32:13.944 0.0
2025-11-29-14:32:14.142 0.0
2025-11-29-14:32:14.304 0.0
2025-11-29-14:32:14.503 0.0
2025-11-29-14:32:14.706 0.0
2025-11-29-14:32:14.905 0.0
2025-11-29-14:32:15.119 0.0
2025-11-29-14:32:15.320 0.0
2025-11-29-14:32:15.518 0.0
2025-11-29-14:32:15.723 0.0
2025-11-29-14:32:15.916 0.0
2025-11-29-14:32:16.405 0.0
2025-11-29-14:32:16.457 0.0
2025-11-29-14:32:16.653 0.0
2025-11-29-14:32:16.853 0.0
2025-11-29-14:32:17.053 0.0
2025-11-29-14:32:17.266 0.0
2025-11-29-14:32:17.461 0.0
2025-11-29-14:32:17.664 0.0
2025-11-29-14:32:17.861 0.0
2025-11-29-14:32:18.063 0.0
2025-11-29-14:32:18.305 0.0
2025-11-29-14:32:18.510 0.0
2025-11-29-14:32:18.801 0.0
2025-11-29-14:32:18.859 0.0
2025-11-29-14:32:19.059 0.0
2025-11-29-14:32:19.266 0.0
2025-11-29-14:32:19.466 0.0
2025-11-29-14:39:42.614 0.0
2025-11-29-14:39:42.644 0.0
2025-11-29-14:39:42.844 0.0
2025-11-29-14:39:43.110 16.2
2025-11-29-14:39:43.250 16.2
2025-11-29-14:39:43.443 0.0
2025-11-29-14:39:43.653 0.0
2025-11-29-14:39:43.855 16.6
2025-11-29-14:39:44.055 16.5
2025-11-29-14:39:44.258 16.5
2025-11-29-14:39:44.464 16.0
2025-11-29-14:39:44.658 0.0
2025-11-29-14:39:44.929 0.0
2025-11-29-14:39:45.344 0.0
2025-11-29-14:39:45.376 0.0
2025-11-29-14:39:45.571 0.0
2025-11-29-14:39:45.789 17.5
2025-11-29-14:39:45.980 16.8
2025-11-29-14:39:46.180 16.9
2025-11-29-14:39:46.383 16.5
2025-11-29-14:39:46.585 16.2
2025-11-29-14:39:46.798 16.3
2025-11-29-14:39:46.994 16.5
2025-11-29-14:39:47.194 16.2
2025-11-29-14:39:47.405 16.3
2025-11-29-14:39:47.603 16.5
2025-11-29-14:39:47.807 16.8
2025-11-29-14:39:48.002 0.0
2025-11-29-14:39:48.216 0.0
2025-11-29-14:39:48.414 0.0
2025-11-29-14:39:48.632 0.0
2025-11-29-14:39:48.841 16.3
2025-11-29-14:39:49.034 0.0
2025-11-29-14:39:49.259 16.2
2025-11-29-14:39:49.461 16.2
2025-11-29-14:39:49.657 16.5
2025-11-29-14:39:49.889 16.2
2025-11-29-14:39:50.058 0.0
2025-11-29-14:39:50.271 16.2
2025-11-29-14:39:50.486 16.3
2025-11-29-14:39:50.693 0.0
2025-11-29-14:39:50.902 16.5
2025-11-29-14:39:51.100 16.3
2025-11-29-14:39:51.295 0.0
2025-11-29-14:39:51.508 16.5
2025-11-29-14:39:51.708 16.5
2025-11-29-14:39:51.928 0.0
2025-11-29-14:39:52.111 0.0
2025-11-29-14:39:52.341 16.3
2025-11-29-14:39:52.508 16.6
2025-11-29-14:39:52.701 16.5
2025-11-29-14:39:52.932 16.2
2025-11-29-14:39:53.122 16.0
2025-11-29-14:39:53.325 16.2
......@@ -162,39 +162,14 @@ class ModelSettingsHandler:
# 按钮
button_layout = QtWidgets.QHBoxLayout()
save_btn = QtWidgets.QPushButton("保存设置")
cancel_btn = QtWidgets.QPushButton("取消")
reset_btn = QtWidgets.QPushButton("重置")
button_layout.addWidget(save_btn)
button_layout.addWidget(reset_btn)
button_layout.addWidget(cancel_btn)
main_layout.addLayout(button_layout)
# 连接按钮事件
def save_settings():
# 更新模型参数
updated_params = model_params.copy()
updated_params.update({
'type': type_edit.text(),
'confidence': confidence_spin.value(),
'iou': iou_spin.value(),
'classes': classes_spin.value(),
'input': input_edit.text(),
'device': device_combo.currentText(),
'batch_size': batch_spin.value(),
'workers': workers_spin.value(),
'epochs': epochs_spin.value(),
'blur_training': blur_spin.value(),
'description': desc_edit.toPlainText()
})
# 保存到模型集页面
self.modelSetPage._model_params[model_name] = updated_params
QtWidgets.QMessageBox.information(dialog, "保存成功", f"模型 '{model_name}' 的设置已保存")
dialog.accept()
def reset_settings():
# 重置所有设置到原始值
type_edit.setText(model_params.get('type', ''))
......@@ -209,7 +184,6 @@ class ModelSettingsHandler:
blur_spin.setValue(model_params.get('blur_training', 100))
desc_edit.setPlainText(model_params.get('description', ''))
save_btn.clicked.connect(save_settings)
reset_btn.clicked.connect(reset_settings)
cancel_btn.clicked.connect(dialog.reject)
......
......@@ -1049,7 +1049,6 @@ class CurvePanelHandler:
from thread_manager.threads.curve_thread import CurveThread
if not CurveThread.is_running():
# 全局曲线线程已停止,不更新UI(静默跳过)
print(f"⚠️ [曲线数据处理-主线程] 曲线线程未运行,跳过更新")
return
except ImportError:
# 如果导入失败,继续处理
......
......@@ -45,6 +45,9 @@ except ImportError:
class ModelLoadingProgressDialog(QDialog):
"""模型加载进度条对话框"""
# 🔥 添加取消信号
cancelRequested = Signal() # 用户点击关闭按钮时发出
def __init__(self, parent=None, total_models: int = 1):
"""
初始化进度条对话框
......@@ -56,6 +59,7 @@ class ModelLoadingProgressDialog(QDialog):
super().__init__(parent)
self.total_models = total_models
self.current_model = 0
self._user_cancelled = False # 标记用户是否取消
self.setupUI()
......@@ -68,11 +72,10 @@ class ModelLoadingProgressDialog(QDialog):
# 设置左上角图标为逻辑图标
self.setWindowIcon(newIcon("逻辑"))
# 移除帮助按钮和关闭按钮
# 🔥 只移除帮助按钮,保留关闭按钮(用户可以点击关闭按钮取消加载)
self.setWindowFlags(
self.windowFlags() &
~Qt.WindowContextHelpButtonHint & # 移除帮助按钮
~Qt.WindowCloseButtonHint # 移除关闭按钮
~Qt.WindowContextHelpButtonHint # 移除帮助按钮
)
# 居中显示
......@@ -213,3 +216,17 @@ class ModelLoadingProgressDialog(QDialog):
self.title_label.setText("模型加载失败")
self.title_label.setStyleSheet("font-weight: bold; padding: 5px 0;")
self.step_label.setText("请检查模型文件和配置")
def closeEvent(self, event):
"""
处理关闭事件(用户点击右上角关闭按钮)
发出取消信号,通知外部停止加载线程
"""
if not self._user_cancelled:
self._user_cancelled = True
print(f"⚠️ [模型加载] 用户取消加载,发出取消信号")
self.cancelRequested.emit()
# 接受关闭事件
event.accept()
......@@ -318,7 +318,6 @@ class CurveThread:
data_points = []
try:
print(f"🔄 [全局曲线线程] 开始加载CSV文件: {csv_filepath}")
with open(csv_filepath, 'r', encoding='utf-8') as f:
line_count = 0
for line in f:
......@@ -349,11 +348,9 @@ class CurveThread:
except ValueError as ve:
pass
print(f"✅ [全局曲线线程] CSV文件加载完成: {csv_filepath}, 共 {len(data_points)} 个数据点")
return data_points
except Exception as e:
print(f"⚠️ [全局曲线线程] 加载CSV到内存失败 {csv_filepath}: {e}")
import traceback
traceback.print_exc()
return []
......@@ -395,7 +392,8 @@ class CurveThread:
return new_lines
except Exception as e:
print(f"⚠️ [全局曲线线程] 增量读取CSV失败 {csv_filepath}: {e}")
import traceback
traceback.print_exc()
return []
@staticmethod
......@@ -418,7 +416,8 @@ class CurveThread:
files.append(os.path.join(directory, name))
return files
except Exception as e:
print(f"⚠️ [全局曲线线程] 无法列出CSV文件: {e}")
import traceback
traceback.print_exc()
return []
@staticmethod
......@@ -491,7 +490,8 @@ class CurveThread:
curve_frame_rate = max(1, min(25, curve_frame_rate))
return curve_frame_rate
except Exception as e:
print(f"⚠️ [全局曲线线程] 读取曲线帧率配置失败: {e}")
import traceback
traceback.print_exc()
# 默认返回2 Hz
return 2
......
......@@ -126,40 +126,30 @@ class ViewHandler:
Returns:
bool: True=curvemission使用的通道中有任意一个检测线程正在运行, False=全部停止
"""
print(f"\n🔍 [检测状态判断] 开始检查...")
if not hasattr(self, 'thread_manager'):
print(f"❌ [检测状态判断] 没有thread_manager")
return False
# 获取当前curvemission选择的任务
if not hasattr(self, 'curvemission'):
print(f"❌ [检测状态判断] 没有curvemission")
return False
mission_name = self.curvemission.currentText()
print(f"📋 [检测状态判断] 当前任务: {mission_name}")
if not mission_name or mission_name == "请选择任务":
print(f"❌ [检测状态判断] 未选择有效任务")
return False
# 🔥 第一层判断:检查任务状态
mission_status = self._getMissionStatus(mission_name)
print(f"📊 [检测状态判断] 任务状态: '{mission_status}'")
if mission_status == "未启动":
print(f"⚠️ [检测状态判断] 任务状态为'未启动',跳过channel_detect_status检查,直接使用历史回放模式(索引1)")
return False
else:
print(f"✅ [检测状态判断] 任务状态为'{mission_status}',继续检查channel_detect_status")
# 获取该任务使用的通道列表
task_channels = self._getTaskChannels(mission_name)
print(f"📡 [检测状态判断] 任务使用的通道: {task_channels}")
if not task_channels:
print(f"❌ [检测状态判断] 任务没有配置通道")
return False
# 将通道名称转换为通道ID(通道1 -> channel1)
......@@ -170,7 +160,6 @@ class ViewHandler:
channel_num = channel_name.replace('通道', '')
channel_ids.append(f'channel{channel_num}')
print(f"🔑 [检测状态判断] 转换后的通道ID: {channel_ids}")
# 检查这些通道的channel_detect_status状态
# 只要有任意一个通道的channel_detect_status为True,就返回True
......@@ -178,16 +167,14 @@ class ViewHandler:
context = self.thread_manager.get_channel_context(channel_id)
if context:
channel_detect_status = context.channel_detect_status
print(f" 🔸 {channel_id}: channel_detect_status={channel_detect_status}, type={type(channel_detect_status)}")
# 确保 channel_detect_status 是布尔值 True
if channel_detect_status is True or channel_detect_status == True:
print(f"✅ [检测状态判断] 发现运行中的检测线程: {channel_id}")
return True
else:
print(f" ⚠️ {channel_id}: 没有context")
# 所有通道的channel_detect_status都为False
print(f"❌ [检测状态判断] 所有通道的检测线程都已停止")
return False
def _getMissionStatus(self, mission_name):
......@@ -437,6 +424,20 @@ class ViewHandler:
except ImportError:
pass
# 🔥 禁用/启用通道面板的查看曲线按钮
# 索引0(实时检测模式)时禁用,索引1(历史回放模式)时启用
if hasattr(self, 'channelPanels'):
for panel in self.channelPanels:
if hasattr(panel, 'btnCurve'):
if target_index == 0:
# 实时检测模式:禁用查看曲线按钮
panel.btnCurve.setEnabled(False)
panel.btnCurve.setToolTip("实时检测模式下无法查看曲线")
else:
# 历史回放模式:启用查看曲线按钮
panel.btnCurve.setEnabled(True)
panel.btnCurve.setToolTip("查看曲线")
# 执行布局切换
current_index = self.curveLayoutStack.currentIndex()
print(f"📍 [布局切换] 当前索引: {current_index}, 目标索引: {target_index}")
......
1曲线模式索引0布局,只显示根据curvemission筛选使用的通道面板失效了
1曲线模式索引0布局,只显示根据curvemission筛选使用的通道面板失效了
......@@ -22,4 +22,7 @@
3启动检测线程时对应任务的对应通道列置为绿色
4新建任务信息文本显示初始默认都为灰色
5单击任务行后该任务mission_status为true时才置黑该任务行
6mission_status判断逻辑,只要任意channelmission值为此任务,则此任务mission_status=true
\ No newline at end of file
6mission_status判断逻辑,只要任意channelmission值为此任务,则此任务mission_status=true
class ModelLoadingProgressDialog(QDialog):
"""模型加载进度条对话框"""
\ No newline at end of file
......@@ -185,7 +185,8 @@ class CurvePanel(QtWidgets.QWidget):
toolbar_layout.addSpacing(10)
# 模式标签(保存为实例变量,以便动态更新)
# 🔥 模式标签已隐藏(用户要求删除左侧布局索引文本标签)
# 保留变量以避免其他代码引用错误,但不添加到布局中
self.mode_label = QtWidgets.QLabel("历史回放")
self.mode_label.setStyleSheet("font-weight: bold; padding: 2px 8px;")
......@@ -197,7 +198,7 @@ class CurvePanel(QtWidgets.QWidget):
except ImportError:
pass
toolbar_layout.addWidget(self.mode_label)
# toolbar_layout.addWidget(self.mode_label) # 🔥 已注释,不显示模式标签
# 任务文件夹选择(下拉选项框)- 响应式布局
self.curvemission = QtWidgets.QComboBox()
......
......@@ -442,13 +442,10 @@ class GeneralSetPanel(QtWidgets.QWidget):
self.start_detection_btn = QtWidgets.QPushButton("开始检测")
self.start_detection_btn.setMinimumSize(scale_w(120), scale_h(35)) # 响应式尺寸
# 保存设置按钮(移到这里)
self.save_btn = QtWidgets.QPushButton("保存设置")
self.save_btn.setMinimumSize(scale_w(100), scale_h(32)) # 响应式尺寸
# 🔥 保存设置按钮已删除(用户要求)
btn_layout.addWidget(self.start_annotation_btn)
btn_layout.addWidget(self.start_detection_btn)
btn_layout.addWidget(self.save_btn)
btn_layout.addStretch()
layout.addWidget(self.annotation_status_label)
......@@ -471,8 +468,8 @@ class GeneralSetPanel(QtWidgets.QWidget):
self.start_annotation_btn.clicked.connect(self._onStartAnnotation)
self.start_detection_btn.clicked.connect(self._onStartDetection)
# 保存设置按钮
self.save_btn.clicked.connect(self._onSaveSettings)
# 🔥 保存设置按钮已删除
# self.save_btn.clicked.connect(self._onSaveSettings)
def _loadTaskIdOptions(self):
"""加载任务编号选项(发送信号给handler处理)"""
......@@ -1568,9 +1565,9 @@ class AnnotationWidget(QtWidgets.QWidget):
# 转换坐标
image_x, image_y = self._labelToImageCoords(event.x(), event.y())
# 🔥 右键点击:取消最后一个标注
# 🔥 右键点击:显示上下文菜单
if event.button() == Qt.RightButton:
self._onRightClick()
self._showContextMenu(event.globalPos(), image_x, image_y)
return
# 左键点击:正常标注流程
......@@ -1923,8 +1920,102 @@ class AnnotationWidget(QtWidgets.QWidget):
# 检查点是否在框内
return left <= x <= right and top <= y <= bottom
def _findBoxAtPosition(self, x, y):
"""
查找点击位置对应的标注框索引
Args:
x: 图像坐标X
y: 图像坐标Y
Returns:
int: 标注框索引(0-based),如果没有找到返回-1
"""
if self.annotation_engine is None:
return -1
# 从后往前遍历(后绘制的框在上层,优先选择)
for i in range(len(self.annotation_engine.boxes) - 1, -1, -1):
box = self.annotation_engine.boxes[i]
cx, cy, size = box
half = size // 2
# 计算检测框的边界
left = cx - half
right = cx + half
top = cy - half
bottom = cy + half
# 检查点是否在框内
if left <= x <= right and top <= y <= bottom:
return i
return -1
def _deleteBoxAtIndex(self, index):
"""
删除指定索引的标注框
Args:
index: 标注框索引(0-based)
"""
if self.annotation_engine is None:
return
if index < 0 or index >= len(self.annotation_engine.boxes):
return
# 删除区域
self.annotation_engine.boxes.pop(index)
# 删除对应的底部点和顶部点
if index < len(self.annotation_engine.bottom_points):
self.annotation_engine.bottom_points.pop(index)
if index < len(self.annotation_engine.top_points):
self.annotation_engine.top_points.pop(index)
# 删除对应的区域名称、高度和状态
if index < len(self.area_names):
self.area_names.pop(index)
if index < len(self.area_heights):
self.area_heights.pop(index)
if index < len(self.area_states):
self.area_states.pop(index)
# 更新显示
self._updateDisplay()
def _showContextMenu(self, global_pos, image_x, image_y):
"""显示右键上下文菜单"""
if self.annotation_engine is None:
return
# 🔥 查找点击位置对应的标注框索引
clicked_box_index = self._findBoxAtPosition(image_x, image_y)
# 创建上下文菜单
context_menu = QtWidgets.QMenu(self)
# 添加删除选项
if clicked_box_index >= 0:
# 点击了某个标注框
area_name = self.area_names[clicked_box_index] if clicked_box_index < len(self.area_names) else f"区域{clicked_box_index + 1}"
delete_action = context_menu.addAction(f"删除区域: {area_name}")
delete_action.setEnabled(True)
else:
# 没有点击任何标注框
delete_action = context_menu.addAction("删除区域")
delete_action.setEnabled(False)
# 显示菜单并获取用户选择
action = context_menu.exec_(global_pos)
# 处理用户选择
if action == delete_action and clicked_box_index >= 0:
self._deleteBoxAtIndex(clicked_box_index)
def _onRightClick(self):
"""右键点击:取消最后一个标注"""
"""删除最后一个标注框(由右键菜单调用)"""
if self.annotation_engine is None:
return
......
......@@ -159,16 +159,7 @@ class ModelSettingDialog(QtWidgets.QDialog):
""")
availableLayout.addWidget(self.modelListWidget)
# 刷新按钮布局 - 居中显示
refresh_button_layout = QtWidgets.QHBoxLayout()
refresh_button_layout.addStretch()
# 刷新按钮 - 使用全局文本按钮样式管理器,仅文本无图标
self.btnRefreshModels = createTextButton(self.tr("刷新列表"), parent=self)
refresh_button_layout.addWidget(self.btnRefreshModels)
refresh_button_layout.addStretch()
availableLayout.addLayout(refresh_button_layout)
# 🔥 刷新按钮已删除(用户要求)
availableGroup.setLayout(availableLayout)
......@@ -184,7 +175,7 @@ class ModelSettingDialog(QtWidgets.QDialog):
"""连接信号槽"""
# 可用模型列表
self.modelListWidget.itemDoubleClicked.connect(self._onModelListDoubleClicked)
self.btnRefreshModels.clicked.connect(self._refreshModelList)
# self.btnRefreshModels.clicked.connect(self._refreshModelList) # 🔥 已删除刷新按钮
def _refreshModelList(self):
"""刷新可用模型列表 - 发射信号请求handler处理"""
......
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