返回
顶部

前言

最近写了一个基于PyQt的程序,在这里记录一下多线程与信号机制的用法

完整项目代码

pycharm配置pyqt开发环境

首先安装pyqt5和pyqt5-tools

python3 -m pip install PyQt5
python3 -m pip install PyQt5-tools

在pycharm的设置中找到External Tools,点击加号进行如下配置:

1606388335174

这里Program就是designer.exe的绝对路径,直接用everything搜索designer.exe即可获取其绝对路径

1606388207758

配置pyuic用于将ui文件编译成py文件:

1606388503631

使用方法如下:

asdasdasda

代码示例

import multiprocessing
from shutil import copyfile

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QStringListModel, QThread, pyqtSignal, QBasicTimer
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from main import Ui_MainWindow
import subprocess
import re
import multiprocessing
import sys
import os
import random
import time

step = 0

class DemoThread(QThread):
    timer = pyqtSignal()
    def run(self) -> None:
        while True:
            self.demo()
            global step
            if step >= 5:
                break
        self.timer.emit()

    def demo(self):
        self.sleep(1)
        #something to do
        global step
        step += 1

class ProcessBarWorkThread(QThread):
    timer = pyqtSignal()
    def run(self) -> None:
        while True:
            #每一秒钟发送一次绘制信号
            self.sleep(1)
            self.timer.emit()

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)
        self.ui = Ui_MainWindow()
        self.setupMyUi(self)
    def setupMyUi(self, MainWindow):
        self.ui.setupUi(MainWindow)
        # 初始化进度条
        global step
        step = 0
        self.ui.progressBar.setValue(0)
        self.ui.pushButton.clicked.connect(self.on_pushButton_click)
################################################CMS扫描模块事件Begin########################################################
    #点击确定开始绘制进度条
    def on_pushButton_click(self):
        self.demoThread = DemoThread()
        #设置接收到信号时触发的方法
        self.demoThread.timer.connect(self.on_demo_finished)
        self.demoThread.start()
        #初始化进度条
        global step
        step = 0
        self.ui.progressBar.setValue(0)
        self.processBarWorkThread = ProcessBarWorkThread()
        #这里使用lambda匿名方法接受进度条控件参数
        self.processBarWorkThread.timer.connect(lambda: self.processBar(self.ui.progressBar))
        self.processBarWorkThread.start()

    #扫描完成,关闭线程
    def on_demo_finished(self):
        self.demoThread.terminate()

    #绘制进度条
    def processBar(self,processBar):
        global step
        processBar.setValue(step/5*100)
        if step >= 5:
            self.processBarWorkThread.terminate()
            QMessageBox.information(self, "info", "演示结束!")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

效果图:

asdasdasda

可以看到代码中写了两个线程类:DemoThreadProcessBarWorkThread,它们两个都继承自QThread

ProcessBarWorkThread类中,首先使用pyqtSignal初始化一个定时器,然后我们通过sleep方法控制信号发送间隔,本示例程序中是一秒发送一次信号,通过connect方法绑定每次接收到信号时出发的动作

self.processBarWorkThread.timer.connect(lambda: self.processBar(self.ui.progressBar))

processBar方法接受一个QProgressBar类型的对象作为参数来确定要对哪一个进度条控件进行绘制

而另一个线程类:DemoThread是我们的程序中的业务代码,也就是真正干活的线程,我们每完成一定的任务就改变一下全局变量step的值,然后当下一次ProcessBarWorkThread发送信号通知processBar方法进行进度条的绘制时,进度条就会发生变化

这两个线程通信的方式就是使用全局变量step