PYQT5学习文档4-多线程应用_线程暂停、继续、中止

根据前面的内容,在界面新增三个按钮(暂停、继续、中止)

重新按照之前的方式重新生成一次py文件,操作可以看前面的内容。

传送门:

PYQT5学习文档2-界面组件使用说明-CSDN博客

PYQT5学习文档3-多线程应用,防止主界面假死-CSDN博客

在主窗口类中新增三个函数、暂停、继续、中止,并且把按钮关联上对应的函数

    # 暂停线程
    def pause_thread(self):
        try:
            #暂停线程
            self.t.pause()
            self.textBrowser.append("暂停!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
            
    # 唤醒线程
    def resume_thread(self):
        try:
            #唤醒线程
            self.t.resume()
            self.textBrowser.append("继续!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
            
    # 停止线程
    def stop_thread(self):
        try:
            #关闭线程
            self.t.terminate()
            self.t = None
            self.textBrowser.append("中止运行!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 

新增关联函数

def  __init__ (self):
        super(mywindow, self).__init__()
        #运行界面
        self.setupUi(self)
        
        #选择文件夹按钮与函数链接
        self.choise_folder.clicked.connect(self.write_folder)
        
        #选择文件按钮函数链接
        self.choise_file.clicked.connect(self.read_file)
        
        #开始按钮函数链接
        self.start.clicked.connect(self.process)
        
        #退出按钮函数链接
        self.exit.clicked.connect(self.clickButtonCloseWindow)
    
        #初始化进度条为0,进度默认范围0-100
        self.progressBar.setProperty("value", 0)
        
        #暂停按钮
        self.paused.clicked.connect(self.pause_thread)
        #继续按钮
        self.continue_.clicked.connect(self.resume_thread)
        #中止按钮
        self.discontinue.clicked.connect(self.stop_thread)

在线程类中新增两个函数,新增三个参数,重写运行程序。

class My_thread(QThread):
    #建立一个信号,信号类型为int型,也可以是其他的型号类型,str,dic,list等。
    num_trig = pyqtSignal(int)

    def __init__(self):
        super(My_thread, self).__init__()
        
        #设置默认状态为假
        self._isPause = False
        
        #调用阻塞线程
        self.cond = QWaitCondition()
        
        self.mutex = QMutex()
        

    def run(self) -> None:
        global n
        n=10
        for i in range(n):
            time.sleep(2)
            #上锁
            self.mutex.lock()  
            
            #如果为真,则上锁,默认状态是假
            if self._isPause:
                #阻塞线程运行
                self.cond.wait(self.mutex)
            # 解锁
            self.mutex.unlock()  
            #传输信号 i+1 
            self.num_trig.emit(i+1)
    
    # 线程暂停
    def pause(self):
        self._isPause = True
 
    # 线程恢复
    def resume(self):
        self._isPause = False
        self.cond.wakeAll()

完整代码如下(界面ui的py文件是生成的,这里没有贴出来,可以看之前的文章):

#读取包
from PyQt5 import QtWidgets

# 导入ui文件转换后的py文件
from test import Ui_Dialog

from PyQt5.QtWidgets import QFileDialog
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QLabel,QHBoxLayout,QWidget,QApplication,QMainWindow,QMessageBox
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QWaitCondition, QMutex

import time

import warnings
warnings.filterwarnings("ignore")


#创建窗口类
class mywindow(QtWidgets.QWidget, Ui_Dialog):
    quit_trig = pyqtSignal()
    
    def  __init__ (self):
        super(mywindow, self).__init__()
        #运行界面
        self.setupUi(self)
        
        #选择文件夹按钮与函数链接
        self.choise_folder.clicked.connect(self.write_folder)
        
        #选择文件按钮函数链接
        self.choise_file.clicked.connect(self.read_file)
        
        #开始按钮函数链接
        self.start.clicked.connect(self.process)
        
        #退出按钮函数链接
        self.exit.clicked.connect(self.clickButtonCloseWindow)
    
        #初始化进度条为0,进度默认范围0-100
        self.progressBar.setProperty("value", 0)
        
        #暂停按钮
        self.paused.clicked.connect(self.pause_thread)
        #继续按钮
        self.continue_.clicked.connect(self.resume_thread)
        #中止按钮
        self.discontinue.clicked.connect(self.stop_thread)
        
    
    
    def write_folder(self):
        #选取文件夹
        foldername = QFileDialog.getExistingDirectory(self, "选取文件夹", "C:/")
        #将选取的文件夹路径写入lineEdit_folder中
        self.lineEdit_folder.setText(foldername)
    
    def read_file(self):
        #选取文件路径
        filename, filetype =QFileDialog.getOpenFileName(self, "选取文件", "C:/", "All Files(*);;Text Files(*.csv)")
        #将路径写入 lineEdit_file 中
        self.lineEdit_file.setText(filename)
        
    def clickButtonCloseWindow(self):
        #调用qt的弹窗消息的库
        a = QMessageBox.question(self, '退出', '是否退出程序?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)      #"退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
        if a == QMessageBox.Yes:  
            self.close()        #接受关闭事件  
        else:  
            pass
    
    # 暂停线程
    def pause_thread(self):
        try:
            #暂停线程
            self.t.pause()
            self.textBrowser.append("暂停!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
            
    # 唤醒线程
    def resume_thread(self):
        try:
            #唤醒线程
            self.t.resume()
            self.textBrowser.append("继续!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
            
    # 停止线程
    def stop_thread(self):
        try:
            #关闭线程
            self.t.terminate()
            self.t = None
            self.textBrowser.append("中止运行!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        except:
            self.textBrowser.append("线程不存在!")
            # 移动光标到底部
            self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
    
    
    
    def process(self):
        
        #输出文件夹路径:
        self.textBrowser.append(f"输出:{self.lineEdit_folder.text()}")
        # 移动光标到底部
        self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        
        #输出文件的路径:
        self.textBrowser.append(f"输出:{self.lineEdit_file.text()}")
        # 移动光标到底部
        self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 
        
        # 实例化一个线程
        self.t = My_thread()    
        # 线程信号绑定到函数setValue上
        self.t.num_trig.connect(self.setValue)      
        #启动线程
        self.t.start()
        
    def setValue(self,v):
        #在textbrowser中显示内容
        self.textBrowser.append(f"输出:{v}")
        # 移动光标到底部
        self.textBrowser.moveCursor(self.textBrowser.textCursor().End) 

        #界面刷新显示(没有以下代码,界面会出现假死现象,循环运行完成之后才会全部显示出来,可以注释掉对比下)
        #多线程的内容等后面再做补充。
        QtWidgets.QApplication.processEvents()

        #设置进度条展示(进度条设置也有刷新的功能,设置进度条后,可以不用上面那个刷新代码,也会有刷新的效果)
        self.progressBar.setProperty("value", (v)/n*100)
    
    
#建立一个线程
class My_thread(QThread):
    #建立一个信号,信号类型为int型,也可以是其他的型号类型,str,dic,list等。
    num_trig = pyqtSignal(int)

    def __init__(self):
        super(My_thread, self).__init__()
        
        #设置默认状态为假
        self._isPause = False
        
        #调用阻塞线程
        self.cond = QWaitCondition()
        
        self.mutex = QMutex()
        

    def run(self) -> None:
        global n
        n=10
        for i in range(n):
            time.sleep(2)
            #上锁
            self.mutex.lock()  
            
            #如果为真,则上锁,默认状态是假
            if self._isPause:
                #阻塞线程运行
                self.cond.wait(self.mutex)
            # 解锁
            self.mutex.unlock()  
            #传输信号 i+1 
            self.num_trig.emit(i+1)
    
    # 线程暂停
    def pause(self):
        self._isPause = True
 
    # 线程恢复
    def resume(self):
        self._isPause = False
        self.cond.wakeAll()
    
    
if __name__=="__main__":
    import sys
    app=QtWidgets.QApplication(sys.argv)
    ui = mywindow()    
    ui.show()
    sys.exit(app.exec_())

其他相关文章,到主页内查看。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PyQt 是一个基于 Python 的 GUI 编程框架,支持多线程编程。在 PyQt 中,可以通过 QThread 类来创建新的线程,还可以使用信号和槽机制来进行不同线程之间的通信。 下面是一个简单的 PyQt 多线程示例: ```python import sys from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel class Worker(QThread): finished = pyqtSignal() progress = pyqtSignal(int) def __init__(self, parent=None): super().__init__(parent) def run(self): for i in range(1, 101): self.progress.emit(i) self.msleep(100) self.finished.emit() class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.label = QLabel("Progress Bar", self) self.label.setGeometry(50, 50, 200, 50) self.thread = Worker(self) self.thread.finished.connect(self.finished) self.thread.progress.connect(self.update_progress) self.thread.start() def update_progress(self, value): self.label.setText(f"Progress: {value}%") def finished(self): self.label.setText("Finished") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 在这个示例中,我们创建了一个名为 Worker 的 QThread 类,该类模拟了一个长时间运行的任务。在 MainWindow 类中,我们创建了一个 Worker 实例,并启动它的运行。在 Worker 类中,我们使用 pyqtSignal 定义了两个信号:finished 和 progress。finished 信号在 Worker 运行结束时发出,progress 信号则在 Worker 运行期间定期发出,以更新进度条。 在 MainWindow 类中,我们将 progress 信号连接到 update_progress() 方法,该方法更新标签文本以显示当前进度。我们还将 finished 信号连接到 finished() 方法,该方法在 Worker 运行结束时更新标签文本。最后,我们调用 thread.start() 方法启动 Worker 线程。 这只是一个简单的 PyQt 多线程示例,还有许多其他的用法和技巧可以学习

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值