前言
最近写了一个基于PyQt的程序,在这里记录一下多线程与信号机制的用法
pycharm配置pyqt开发环境
首先安装pyqt5和pyqt5-tools
python3 -m pip install PyQt5
python3 -m pip install PyQt5-tools
在pycharm的设置中找到External Tools
,点击加号进行如下配置:
这里Program
就是designer.exe的绝对路径,直接用everything搜索designer.exe即可获取其绝对路径
配置pyuic用于将ui文件编译成py文件:
使用方法如下:
代码示例
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_())
效果图:
可以看到代码中写了两个线程类:DemoThread
和ProcessBarWorkThread
,它们两个都继承自QThread
在ProcessBarWorkThread
类中,首先使用pyqtSignal
初始化一个定时器,然后我们通过sleep方法控制信号发送间隔,本示例程序中是一秒发送一次信号,通过connect方法绑定每次接收到信号时出发的动作
self.processBarWorkThread.timer.connect(lambda: self.processBar(self.ui.progressBar))
processBar
方法接受一个QProgressBar
类型的对象作为参数来确定要对哪一个进度条控件进行绘制
而另一个线程类:DemoThread
是我们的程序中的业务代码,也就是真正干活的线程,我们每完成一定的任务就改变一下全局变量step
的值,然后当下一次ProcessBarWorkThread
发送信号通知processBar
方法进行进度条的绘制时,进度条就会发生变化
这两个线程通信的方式就是使用全局变量step