PyQt5自定义信号与槽带示例讲解

  • 简单的来说,信号与槽可以理解成是你说话,我回话,你不说话,我也不bb这种形式。

  • PyQt自带的信号与槽写法如下:

self.btn_DownloadSingleLink.clicked.connect(self.DownloadSingleLink)

此处的含义是按钮的点击事件的绑定
这个比较好理解,因为自带的,所以不需要自己设定信号事件

接下来简单说一下自定义信号事件的申明
首先,需要引入两个库from PyQt5.QtCore import pyqtSignal,QObject
一个是信号类,一个是基类
定义信号比较简单
在基类下定义类属性重点是类属性,而不是在init初始化下方法属性,不然会报错。

class Ui_MainWindow(QObject):
    signal_single_link = pyqtSignal(str,str,str)  #定义下载单条链接的信号参数(文件名,文件大小,文件进度)
    def __init__(self):
        self.download_url = ''
        super(Ui_MainWindow, self).__init__()

在这边类里面,定义了signal_single_link这个信号,需要传递的参数是三个str类型的参数。

第二步时绑定槽,就很像你说话,总不能对着空气说,这样很无聊。
绑定槽函数的方法比较常见。
像这样。

self.signal_single_link.connect(self.showSingalInfo)

这个代码的含义就是绑定了showSignalInfo方法。
第三步 就是发送消息给槽。用的是emit方法
就像这样

self.signal_single_link.emit(str(name),str(file_size),str(formatFloat(p)))

完整的代码如下

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ZL.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QMessageBox,QFileDialog
import time
import requests
import _thread
from PyQt5.QtGui import *
from PyQt5.QtCore import pyqtSignal,QObject

def convertCookie(cookie_val):
    # 转成字典格式
    return dict(map(lambda x: x.split('='), cookie_val.split(";")))

def formatFloat(num):
    return '{:.2f}'.format(num)

class Ui_MainWindow(QObject):
    signal_single_link = pyqtSignal(str,str,str)  #定义下载单条链接的信号参数(文件名,文件大小,文件进度)
    def __init__(self):
        self.download_url = ''
        super(Ui_MainWindow, self).__init__()
        #定义测试信号
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(700, 600)
        MainWindow.setMinimumSize(QtCore.QSize(700, 600))
        MainWindow.setMaximumSize(QtCore.QSize(700, 600))
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        MainWindow.setFont(font)
        MainWindow.setStyleSheet("")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 681, 41))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setSpacing(10)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.lineEdit_Cookies = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
        self.lineEdit_Cookies.setEnabled(True)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.lineEdit_Cookies.setFont(font)
        self.lineEdit_Cookies.setObjectName("lineEdit_Cookies")
        self.horizontalLayout.addWidget(self.lineEdit_Cookies)
        self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(10, 60, 681, 41))
        self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.label_2 = QtWidgets.QLabel(self.horizontalLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout_2.addWidget(self.label_2)
        self.lineEdit_SingleLink = QtWidgets.QLineEdit(self.horizontalLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.lineEdit_SingleLink.setFont(font)
        self.lineEdit_SingleLink.setStyleSheet("")
        self.lineEdit_SingleLink.setObjectName("lineEdit_SingleLink")
        self.horizontalLayout_2.addWidget(self.lineEdit_SingleLink)
        self.btn_DownloadSingleLink = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.btn_DownloadSingleLink.setFont(font)
        self.btn_DownloadSingleLink.setObjectName("btn_DownloadSingleLink")
        self.btn_DownloadSingleLink.clicked.connect(self.DownloadSingleLink)
        self.horizontalLayout_2.addWidget(self.btn_DownloadSingleLink)
        self.horizontalLayoutWidget_3 = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(10, 110, 681, 41))
        self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3)
        self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.label_3 = QtWidgets.QLabel(self.horizontalLayoutWidget_3)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.horizontalLayout_3.addWidget(self.label_3)
        self.btn_OpenTxtPath = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
        self.btn_OpenTxtPath.setObjectName("btn_OpenTxtPath")
        self.horizontalLayout_3.addWidget(self.btn_OpenTxtPath)
        self.label_txt_path = QtWidgets.QLabel(self.horizontalLayoutWidget_3)
        self.label_txt_path.setObjectName("label_txt_path")
        self.horizontalLayout_3.addWidget(self.label_txt_path)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem)
        self.btn_SetThreadNum = QtWidgets.QPushButton(self.horizontalLayoutWidget_3)
        self.btn_SetThreadNum.setObjectName("btn_SetThreadNum")
        self.horizontalLayout_3.addWidget(self.btn_SetThreadNum)
        self.horizontalLayoutWidget_5 = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget_5.setGeometry(QtCore.QRect(10, 560, 681, 41))
        self.horizontalLayoutWidget_5.setObjectName("horizontalLayoutWidget_5")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_5)
        self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_5.addItem(spacerItem1)
        self.btn_OneDownload = QtWidgets.QPushButton(self.horizontalLayoutWidget_5)
        self.btn_OneDownload.setObjectName("btn_OneDownload")
        self.horizontalLayout_5.addWidget(self.btn_OneDownload)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_5.addItem(spacerItem2)
        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 159, 681, 391))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tableWidget = QtWidgets.QTableWidget(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        self.tableWidget.setFont(font)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(4)
        self.tableWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        item.setFont(font)
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        item.setFont(font)
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        item.setFont(font)
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setPointSize(10)
        item.setFont(font)
        self.tableWidget.setHorizontalHeaderItem(3, item)
        self.verticalLayout.addWidget(self.tableWidget)
        self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.label_4.setObjectName("label_4")
        self.verticalLayout.addWidget(self.label_4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.signal_single_link.connect(self.showSingalInfo)
        #绑定测试信号:
    def showSingalInfo(self,file_name,file_size,file_progress):
        self.label_txt_path.setText('文件名:'+file_name+'文件大小:'+file_size+'文件进度:'+file_progress)
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "筑龙批量下载工具"))
        self.label.setText(_translate("MainWindow", "请输入登录Cookies:"))
        self.label_2.setText(_translate("MainWindow", "请输入单条链接:"))
        self.btn_DownloadSingleLink.setText(_translate("MainWindow", "点击下载"))
        self.label_3.setText(_translate("MainWindow", "请选择txt文件:"))
        self.btn_OpenTxtPath.setText(_translate("MainWindow", "点击打开txt文件"))
        self.label_txt_path.setText(_translate("MainWindow", "显示txt文件路径"))
        self.btn_SetThreadNum.setText(_translate("MainWindow", "设置线程数"))
        self.btn_OneDownload.setText(_translate("MainWindow", "一键下载"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "序号"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "文件名"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow", "文件大小"))
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText(_translate("MainWindow", "当前进度"))
        self.label_4.setText(_translate("MainWindow", "                                tips:登录Cookies为必填项,默认线程数为5"))
    def DownloadSingleLink(self):
        # brief:下载单条链接
        self.cookie = self.lineEdit_Cookies.text().strip()
        if self.cookie == '':
            QMessageBox.warning(None,'下载单条链接','cookie为空,请输入cookie后再下载!')
            return
        if self.cookie != '':
            cookie_str = convertCookie(self.cookie)
            self.download_url = self.lineEdit_SingleLink.text().strip()
            if self.download_url !='':
                download_list = self.download_url.split('aid=')
                download_name = download_list[len(download_list)-1]+'.pdf'
                _thread.start_new_thread(self.downloadFile,(download_name,self.download_url,cookie_str))#Pdf下载

    def downloadFile(self,name, url, login_cookie):
        '''
        :param name:下载保存的名称
        :param url: 下载链接
        :return:
        '''
        headers = {'Proxy-Connection': 'keep-alive'}
        r = requests.get(url, stream=True, headers=headers, cookies=login_cookie)
        length = float(r.headers['content-length'])
        Download_size_M = length / 1048576
        file_size = str(round(Download_size_M, 1)) + 'M'
        f = open(name, 'wb')
        count = 0
        count_tmp = 0
        time1 = time.time()
        for chunk in r.iter_content(chunk_size=512):
            if chunk:
                f.write(chunk)
                count += len(chunk)
                if time.time() - time1 > 2:
                    p = count / length * 100
                    speed = (count - count_tmp) / 1024 / 1024 / 2
                    count_tmp = count
                    print(name + ': ' + formatFloat(p) + '%' + ' Speed: ' + formatFloat(speed) + 'M/S')
                    self.signal_single_link.emit(str(name),str(file_size),str(formatFloat(p)))
                    time1 = time.time()
        f.close()

if __name__ == '__main__':
    #加密程序:
    res = requests.get('https://duhuifeng.github.io/')
    if res.text.strip() == '1':
        app = QApplication(sys.argv)
        MainWindow = QMainWindow()
        ui = Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())
    else:
        print('error!')

作用是下载过程中,传进度返回给主线程显示
一个知识点:在PyQt中UI线程只能在主线程中进行。

运行程序:
PyQt5自定义信号与槽带示例讲解_第1张图片

显而易见,明显传递消息成功!说明信号与槽建立成功,信号与槽的玩法还有很多,这里只是简单介绍这种而已

你可能感兴趣的:(Python)