这里主要是介绍了信号与槽的实现和连接方式。
信号与槽
网络训练任务线程定义
from PyQt5.QtCore import QObject
from GUI.model_thread.th_CLAWorker import CLA_Worker
from GUI.model_thread.th_SSEWorker import SSE_Worker
from GUI.model_thread.th_ODWorker import OD_Worker
class Main_Thread(QObject):
def __init__(self, params: dict, TaskName='图像分类'):
super().__init__()
self.Woker = None
if TaskName == '图像分类':
self.Woker = CLA_Worker(params)
elif TaskName == '语义分割':
self.Woker = SSE_Worker(params)
elif TaskName == '目标检测':
self.Woker = OD_Worker(params)
信号中转站定义
from PyQt5.QtCore import QObject, pyqtSignal
class SignalStation(QObject):
"""
信号中转站单例,用于在线程中发送信号
"""
obj = None # 对象第一次为None
send_msg = pyqtSignal(str, int) # 传递消息。
send_progress = pyqtSignal(float) # 传递进度消息。
def __new__(cls, *args, **kwargs): # 单例模式
if cls.obj is None: # 如果对象为None
cls.obj = super().__new__(cls) # 就创建一个对象
return cls.obj # 否则直接返回
def __init__(self):
super().__init__()
pass
槽函数定义
@pyqtSlot()
def on_ParametersTable_ValueChanged(self):
row = self.Parameters_tableWidget.currentRow()
if row >= 0:
item = self.Parameters_tableWidget.currentItem
if item is not None:
control_type = Config_Parameters[row]['控件类型']
if control_type == 'ComboBox':
Config_Parameters[row]['默认值'] = self.Parameters_tableWidget.cellWidget(row, 1).currentText()
elif control_type == 'CheckBox':
Config_Parameters[row]['默认值'] = self.Parameters_tableWidget.cellWidget(row, 1).isChecked()
elif control_type == 'LineEdit':
Config_Parameters[row]['默认值'] = self.Parameters_tableWidget.cellWidget(row, 1).text()
elif control_type == 'PushButton':
Config_Parameters[row]['默认值'] = self.Parameters_tableWidget.cellWidget(row, 1).text()
print(Config_Parameters)
@pyqtSlot()
def slot_set_root_folder(self):
qdialog = QFileDialog()
folder_path = qdialog.getExistingDirectory(None, "选择文件夹", self.desktop_path, qdialog.ShowDirsOnly)
if folder_path != '':
self.root_folder_edit.setText(folder_path)
@pyqtSlot()
def slot_set_sub_folder(self):
signalsource = self.sender().objectName()
qdialog = QFileDialog()
folder_path = qdialog.getExistingDirectory(None, "选择文件夹", self.desktop_path, qdialog.ShowDirsOnly)
if folder_path != '':
folder_name = os.path.basename(folder_path)
if signalsource == 'images_folder_button':
self.images_folder_edit.setText(folder_name)
elif signalsource == 'label_folder_button':
self.label_folder_edit.setText(folder_name)
elif signalsource == 'split_folder_button':
self.split_folder_edit.setText(folder_name)
@pyqtSlot()
def on_tasks_comboBox_index_changed(self):
self.update_network_names()
self.update_network_versions()
self.update_network_backbones()
@pyqtSlot()
def on_network_names_comboBox_index_changed(self):
self.update_network_versions()
self.update_network_backbones()
@pyqtSlot()
def on_network_versions_comboBox_index_changed(self):
self.update_network_config()
@pyqtSlot()
def on_network_backbones_comboBox_index_changed(self):
self.update_network_config()
@pyqtSlot(float)
def update_progressBar(self, current_value):
if current_value > 1.0:
current_value = 1
self.progressBar.setValue(int(current_value * 100))
self.progressBar.setFormat("Epoch: {:.2f}%".format(current_value * 100))
@pyqtSlot()
def slot_debug(self):
v = self.progressBar.value()
v += 1
@pyqtSlot()
def slot_startTask(self):
params = self.get_table_parameters()
# 实例化线程
try:
self.thread = QThread()
self.worker = Main_Thread(params, TaskName=self.tasks_comboBox.currentText()).Woker
self.worker.moveToThread(self.thread)
# 连接线程的信号
self.thread.started.connect(self.worker.run)
self.thread.finished.connect(self.thread.deleteLater)
self.thread.start()
except Exception as error:
self.slot_print(self.network_names_comboBox.currentText(), 3)
self.slot_print(self.network_versions_comboBox.currentText(), 3)
self.slot_print(error, 3)
@pyqtSlot()
def slot_stopTask(self):
if self.thread.isRunning():
self.thread.quit()
self.thread.wait()
self.thread.deleteLater()
self.Thread_SignalStation.send_msg.disconnect(self._print_)
self.Thread_SignalStation.send_progress.disconnect(self.update_progressBar)
def update_network_names(self):
self.network_names_comboBox.currentIndexChanged.disconnect(self.on_network_names_comboBox_index_changed) # 断开连接
selected_task = self.tasks_comboBox.currentText()
for task in NetworkTypeParams:
if task["ID"] == selected_task:
self.network_names_comboBox.clear()
names = [item['NetworkType'] for item in task["Ranges"]]
self.network_names_comboBox.addItems(names)
break
self.network_names_comboBox.currentIndexChanged.connect(self.on_network_names_comboBox_index_changed) # 重新连接
def update_network_versions(self):
self.network_versions_comboBox.currentIndexChanged.disconnect(self.on_network_versions_comboBox_index_changed) # 断开连接
self.network_versions_comboBox.clear()
versions = self.get_network_versions()
self.network_versions_comboBox.addItems(versions)
self.network_versions_comboBox.currentIndexChanged.connect(self.on_network_versions_comboBox_index_changed) # 重新连接
# self.update_network_config()
def update_network_backbones(self):
self.network_backbones_comboBox.currentIndexChanged.disconnect(self.on_network_backbones_comboBox_index_changed) # 断开连接
self.network_backbones_comboBox.clear()
backbones = self.get_network_backbones()
self.network_backbones_comboBox.addItems(backbones)
self.network_backbones_comboBox.currentIndexChanged.connect(self.on_network_backbones_comboBox_index_changed) # 重新连接
self.update_network_config()
def update_network_config(self):
var = (f"Task: {self.tasks_comboBox.currentText()} | "
f"NetworkType: {self.network_names_comboBox.currentText()} | "
f"Version: {self.network_versions_comboBox.currentText()} | "
f"Backbone: {self.network_backbones_comboBox.currentText()}")
self.loginfo_textEdit.append(validFormat.format(f"{var}")) # 该内容显示为蓝色
if self.network_versions_comboBox.currentText() == 'None':
self.network_versions_comboBox.setCurrentIndex(0)
self.switch_config(self.tasks_comboBox.currentText())
def get_network_versions(self):
selected_task = self.tasks_comboBox.currentText()
selected_name = self.network_names_comboBox.currentText()
if not selected_task or not selected_name:
return []
for task in NetworkTypeParams:
if task["ID"] == selected_task:
versions = [option['Version'] for option in task['Ranges'] if option['NetworkType'] == selected_name][0]
return versions
return []
def get_network_backbones(self):
selected_task = self.tasks_comboBox.currentText()
selected_name = self.network_names_comboBox.currentText()
if not selected_task or not selected_name:
return []
for task in NetworkTypeParams:
if task["ID"] == selected_task:
versions = [option['Backbones'] for option in task['Ranges'] if option['NetworkType'] == selected_name][0]
return versions
return []
def get_table_parameters(self):
# 读取QTableWidget并创建参数字典
parser = dict()
for i in range(len(Config_Parameters)):
param_name = self.Parameters_tableWidget.item(i, 0).text()
param_id = [item['ID'] for item in Config_Parameters if item['名称'] == param_name][0]
cell_widget = self.Parameters_tableWidget.cellWidget(i, 1)
if isinstance(cell_widget, QComboBox): # 如果参数取值是下拉框
default_value = cell_widget.currentText()
default_value = self.str_to_numeric(default_value)
elif isinstance(cell_widget, QCheckBox): # 如果参数取值是复选框
default_value = cell_widget.isChecked()
else: # 其他情况直接获取文本框内容
default_value = cell_widget.text()
default_value = self.str_to_numeric(default_value)
parser[param_id] = default_value
parser['dataset_path'] = self.root_folder_edit.text()
parser["backbone"] = self.network_backbones_comboBox.currentText()
version_name = self.network_versions_comboBox.currentText() if self.network_versions_comboBox.currentText() != 'none' else ''
parser["model_name"] = self.network_names_comboBox.currentText() + version_name
return parser
def switch_config(self, task_name="图像分类"):
if task_name == "图像分类":
self.label_folder_label.setEnabled(False)
self.label_folder_edit.setEnabled(False)
self.label_folder_button.setEnabled(False)
elif task_name == "目标检测":
self.label_folder_label.setEnabled(True)
self.label_folder_edit.setEnabled(True)
self.label_folder_button.setEnabled(True)
elif task_name == "实例分割":
self.label_folder_label.setEnabled(True)
self.label_folder_edit.setEnabled(True)
self.label_folder_button.setEnabled(True)
elif task_name == "语义分割":
self.label_folder_label.setEnabled(True)
self.label_folder_edit.setEnabled(True)
self.label_folder_button.setEnabled(True)
def str_to_numeric(self, string):
if '.' in string or 'e' in string.lower():
try:
value = float(string)
except ValueError:
value = string
elif '[' in string and ']' in string:
return list(map(self.str_to_numeric, string[1:-1].split(',')))
else:
try:
value = int(string)
except ValueError:
value = string
return value
@pyqtSlot(str, int)
def slot_print(self, msg, FormatFlag=1):
if FormatFlag == 1:
self.loginfo_textEdit.append(validFormat.format(msg))
elif FormatFlag == 2:
self.loginfo_textEdit.append(warningFormat.format(msg))
elif FormatFlag == 3:
self.loginfo_textEdit.append(errorFormat.format(msg))