【三】从小白开始使用Python一步一步搭建一个深度学习UI界面【信号与槽】

这里主要是介绍了信号与槽的实现和连接方式。

信号与槽

网络训练任务线程定义

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))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多巴胺耐受

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值