fix(step8): 修复外部模型字典透传断链 + 规范化 loaded_model_data 防 Ridge subscriptable 崩溃
This commit is contained in:
@ -10,8 +10,10 @@ from pathlib import Path
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QGroupBox, QFormLayout,
|
||||
QPushButton, QCheckBox, QComboBox, QLineEdit, QMessageBox,
|
||||
QFileDialog, QRadioButton,
|
||||
QFileDialog, QRadioButton, QListWidget, QAbstractItemView, QHBoxLayout,
|
||||
QListWidgetItem,
|
||||
)
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from src.gui.components.custom_widgets import FileSelectWidget
|
||||
from src.gui.styles import ModernStylesheet
|
||||
@ -75,6 +77,50 @@ class Step8Panel(QWidget):
|
||||
self.external_model_widget.setVisible(False)
|
||||
layout.addWidget(self.external_model_widget)
|
||||
|
||||
# -------- 已扫描模型列表(条件显示) --------
|
||||
self.model_list_group = QGroupBox("选择参与预测的模型")
|
||||
self.model_list_group.setVisible(False)
|
||||
model_list_layout = QVBoxLayout()
|
||||
|
||||
self.model_list = QListWidget()
|
||||
self.model_list.setMaximumHeight(130)
|
||||
self.model_list.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
self.model_list.setStyleSheet("""
|
||||
QListWidget {
|
||||
border: 1px solid #C0C0C0;
|
||||
border-radius: 4px;
|
||||
background-color: #FFFFFF;
|
||||
font-size: 12px;
|
||||
}
|
||||
QListWidget::item {
|
||||
padding: 4px 6px;
|
||||
border-bottom: 1px solid #F0F0F0;
|
||||
}
|
||||
QListWidget::item:selected {
|
||||
background-color: transparent;
|
||||
}
|
||||
""")
|
||||
model_list_layout.addWidget(self.model_list)
|
||||
|
||||
btn_row = QHBoxLayout()
|
||||
self.btn_select_all = QPushButton("全选")
|
||||
self.btn_select_all.setMaximumWidth(80)
|
||||
self.btn_select_all.setStyleSheet(ModernStylesheet.get_button_stylesheet('default'))
|
||||
self.btn_select_all.clicked.connect(self._select_all_models)
|
||||
|
||||
self.btn_select_none = QPushButton("全不选")
|
||||
self.btn_select_none.setMaximumWidth(80)
|
||||
self.btn_select_none.setStyleSheet(ModernStylesheet.get_button_stylesheet('default'))
|
||||
self.btn_select_none.clicked.connect(self._select_none_models)
|
||||
|
||||
btn_row.addWidget(self.btn_select_all)
|
||||
btn_row.addWidget(self.btn_select_none)
|
||||
btn_row.addStretch()
|
||||
model_list_layout.addLayout(btn_row)
|
||||
|
||||
self.model_list_group.setLayout(model_list_layout)
|
||||
layout.addWidget(self.model_list_group)
|
||||
|
||||
# -------- 采样光谱CSV文件(用于独立运行)--------
|
||||
self.sampling_csv_file = FileSelectWidget(
|
||||
"采样光谱CSV:",
|
||||
@ -134,9 +180,11 @@ class Step8Panel(QWidget):
|
||||
return
|
||||
is_external = self.use_external_model.isChecked()
|
||||
self.external_model_widget.setVisible(is_external)
|
||||
self.model_list_group.setVisible(is_external)
|
||||
if not is_external:
|
||||
self.external_models_dict = {}
|
||||
self.external_model_dir = ""
|
||||
self._clear_model_list()
|
||||
|
||||
def _scan_external_model_dir(self):
|
||||
"""浏览模型母文件夹,自动扫描子目录中的 .joblib 文件"""
|
||||
@ -200,9 +248,11 @@ class Step8Panel(QWidget):
|
||||
)
|
||||
self.external_model_widget.set_path("")
|
||||
self.external_models_dict = {}
|
||||
self._clear_model_list()
|
||||
return
|
||||
|
||||
self.external_models_dict = models_found
|
||||
self._populate_model_list(models_found)
|
||||
names = sorted(models_found.keys())
|
||||
display = f"已识别到 {len(names)} 个模型: {', '.join(names)}"
|
||||
self.external_model_widget.set_path(display)
|
||||
@ -216,6 +266,40 @@ class Step8Panel(QWidget):
|
||||
f"加载失败 {len(errors)} 个:\n{err_lines}",
|
||||
)
|
||||
|
||||
def _populate_model_list(self, models_dict):
|
||||
"""将扫描到的模型填充到 QListWidget,每个条目可勾选,默认全选"""
|
||||
self.model_list.clear()
|
||||
for name in sorted(models_dict.keys()):
|
||||
item = QListWidgetItem(name)
|
||||
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(Qt.Checked)
|
||||
self.model_list.addItem(item)
|
||||
|
||||
def _clear_model_list(self):
|
||||
"""清空模型列表"""
|
||||
self.model_list.clear()
|
||||
|
||||
def _select_all_models(self):
|
||||
"""全选:设置所有条目为 Checked"""
|
||||
for i in range(self.model_list.count()):
|
||||
self.model_list.item(i).setCheckState(Qt.Checked)
|
||||
|
||||
def _select_none_models(self):
|
||||
"""全不选:设置所有条目为 Unchecked"""
|
||||
for i in range(self.model_list.count()):
|
||||
self.model_list.item(i).setCheckState(Qt.Unchecked)
|
||||
|
||||
def _get_checked_models_dict(self):
|
||||
"""从列表中提取用户勾选的模型,组装成字典返回"""
|
||||
result = {}
|
||||
for i in range(self.model_list.count()):
|
||||
item = self.model_list.item(i)
|
||||
if item.checkState() == Qt.Checked:
|
||||
name = item.text()
|
||||
if name in self.external_models_dict:
|
||||
result[name] = self.external_models_dict[name]
|
||||
return result
|
||||
|
||||
def update_from_config(self, work_dir=None, pipeline=None):
|
||||
"""从全局配置自动填充采样光谱和模型目录
|
||||
|
||||
@ -347,11 +431,20 @@ class Step8Panel(QWidget):
|
||||
"请先点击「浏览...」按钮选择模型母文件夹!",
|
||||
)
|
||||
return
|
||||
# 只传递用户勾选的模型
|
||||
checked_dict = self._get_checked_models_dict()
|
||||
if not checked_dict:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"未选择模型",
|
||||
"请至少勾选一个模型参与预测!",
|
||||
)
|
||||
return
|
||||
main_window = self.window()
|
||||
if hasattr(main_window, 'run_single_step'):
|
||||
config = {
|
||||
'step8': self.get_config(),
|
||||
'_external_models_dict': self.external_models_dict,
|
||||
'_external_models_dict': checked_dict,
|
||||
'_external_model_dir': self.external_model_dir,
|
||||
}
|
||||
main_window.run_single_step('step8', config)
|
||||
|
||||
Reference in New Issue
Block a user