PyQt5多线程QThread

QThread的要点讲解

在PyQt5中,QThread 类提供了一种方便的方式来实现多线程。多线程允许我们在应用程序中执行一些耗时的任务,而不会阻塞主线程,从而保持用户界面的响应性。下面是关于PyQt5中多线程QThread的一些要点:

创建子类: 通常,我们会创建一个继承自QThread的子类,该子类将包含我们希望在独立线程中执行的任务。这个子类可以包含信号,以便在线程中定期发送消息或结果给主线程。

from PyQt5.QtCore import QThread, pyqtSignal

class WorkerThread(QThread):
    update_signal = pyqtSignal(str)

    def run(self):
        # 在这里执行耗时任务
        self.update_signal.emit("任务完成")
  1. 重写 run 方法:QThread的子类中,我们需要重写run方法。run方法包含了在线程中实际执行的任务。在这个例子中,我们发射了一个信号来通知任务完成。

  2. 使用信号和槽进行通信: 由于线程不能直接访问GUI元素,我们需要使用信号和槽机制来进行线程间通信。在上面的例子中,update_signal信号用于在工作线程中发射消息,而在主线程中我们可以连接这个信号到一个槽函数,以处理这个消息。

worker = WorkerThread()
worker.update_signal.connect(main_window.handle_update)

启动和管理线程: 一旦创建了QThread的子类实例,我们可以通过调用start方法来启动线程。通常,我们会在主线程中创建线程实例,并在需要时启动它们。线程的生命周期应该由我们负责管理,包括在适当的时机停止线程。

移动到线程中:

thread = QThread()
my_object = MyObject()  # 自定义的类,可能包含一些耗时任务

my_object.moveToThread(thread)
thread.started.connect(my_object.run)
thread.start()
  • moveToThread 方法用于将一个对象移到特定的线程中。
  • started 信号表示线程已经启动,连接到需要在线程中执行的方法。

安全终止线程: 在终止线程时,最好使用一种安全的方式。在上述例子中,我们使用了terminate方法,但这不是最佳实践。更好的方式是通过设置一个标志位,在线程的run方法中检查这个标志位,并在需要时退出线程。

QThread为我们提供了一个方便的方式来在PyQt5中处理多线程,通过信号和槽机制,可以实现主线程和工作线程之间的通信,从而有效地管理应用程序中的异步任务。在使用多线程时,确保遵循最佳实践,以避免潜在的线程安全问题。

多进度条案例详解

Worker类详解

class Worker(QObject):
    update_progress_signal = pyqtSignal(int)

    def __init__(self, index):
        super().__init__()
        self.index = index
        self.progress_value = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_progress)

    def start_progress(self):
        self.timer.start(100)

    def pause_progress(self):
        self.timer.stop()

    def update_progress(self):
        self.progress_value += 1
        if self.progress_value > 100:
            self.progress_value = 0

        self.update_progress_signal.emit(self.progress_value)
  1. class Worker(QObject)::定义一个名为 Worker 的类,继承自 QObject。这是一个用于执行工作的类,通过多线程运行。

  2. update_progress_signal = pyqtSignal(int):在 Worker 类中创建一个信号,用于在工作线程中发送更新的进度值给主线程。

  3. def __init__(self, index):Worker 类的构造函数,接收一个参数 index,表示工作线程的索引。

  4. super().__init__():调用父类的构造函数。

  5. self.index = index:将传入的索引保存在实例变量 self.index 中,以便在工作线程中使用。

  6. self.progress_value = 0:初始化一个实例变量 self.progress_value 用于存储进度值,初始值为0。

  7. self.timer = QTimer(self):创建一个 QTimer 对象,用于定期触发 timeout 信号,以便更新进度。

  8. self.timer.timeout.connect(self.update_progress):将 timeout 信号连接到 update_progress 方法,表示每次定时器超时时都会执行 update_progress 方法。

  9. def start_progress(self)::开始进度的方法。调用该方法会启动定时器,使其每100毫秒触发一次 timeout 信号。

  10. def pause_progress(self)::暂停进度的方法。调用该方法会停止定时器,使其不再触发 timeout 信号。

  11. def update_progress(self)::更新进度的方法,由定时器触发。每次调用该方法,进度值加1,如果超过100,则重置为0,并通过发射信号 update_progress_signal 将更新后的进度值发送给主线程。

  12. self.update_progress_signal.emit(self.progress_value):通过 emit 方法发射 update_progress_signal 信号,将当前的进度值发送给主线程。

  13. ProgressBarExample类详解

  14. class ProgressBarExample(QWidget):
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            self.progress_bars = [QProgressBar(self), QProgressBar(self), QProgressBar(self)]
            self.start_buttons = [QPushButton('开始', self), QPushButton('开始', self), QPushButton('开始', self)]
            self.pause_buttons = [QPushButton('暂停', self), QPushButton('暂停', self), QPushButton('暂停', self)]
    
            self.layout = QVBoxLayout()
    
            for progress_bar, start_button, pause_button in zip(self.progress_bars, self.start_buttons, self.pause_buttons):
                self.layout.addWidget(progress_bar)
                self.layout.addWidget(start_button)
                self.layout.addWidget(pause_button)
    
            self.setLayout(self.layout)
    
            self.threads = [QThread() for _ in range(3)]
            self.workers = [Worker(i) for i in range(3)]
    
            for thread, worker, start_button, pause_button, progress_bar in zip(
                    self.threads, self.workers, self.start_buttons, self.pause_buttons, self.progress_bars):
                worker.moveToThread(thread)
                start_button.clicked.connect(worker.start_progress)
                pause_button.clicked.connect(worker.pause_progress)
                worker.update_progress_signal.connect(lambda value, pb=progress_bar: self.update_progress(pb, value))
                thread.start()
    
            self.setGeometry(300, 300, 300, 300)
            self.setWindowTitle('多线程进度条示例')
            self.show()
    
        def update_progress(self, progress_bar, value):
            progress_bar.setValue(value)

  15. class ProgressBarExample(QWidget)::定义一个名为 ProgressBarExample 的类,继承自 QWidget,表示主窗口。

  16. def __init__(self):ProgressBarExample 类的构造函数。

  17. super().__init__():调用父类的构造函数,确保正确初始化窗口。

  18. self.initUI():调用 initUI 方法,用于初始化用户界面。

  19. def initUI(self):ProgressBarExample 类的初始化用户界面方法。

  20. self.progress_bars = [QProgressBar(self), QProgressBar(self), QProgressBar(self)]:创建一个包含3个 QProgressBar 控件的列表,表示3个进度条。

  21. self.start_buttons = [QPushButton('开始', self), QPushButton('开始', self), QPushButton('开始', self)]:创建一个包含3个 QPushButton 控件的列表,表示3个开始按钮。

  22. self.pause_buttons = [QPushButton('暂停', self), QPushButton('暂停', self), QPushButton('暂停', self)]:创建一个包含3个 QPushButton 控件的列表,表示3个暂停按钮。

  23. self.layout = QVBoxLayout():创建一个垂直布局管理器。

  24. for progress_bar, start_button, pause_button in zip(self.progress_bars, self.start_buttons, self.pause_buttons)::使用 zip 函数将进度条、开始按钮和暂停按钮进行配对。

  25. self.layout.addWidget(progress_bar):将进度条添加到垂直布局中。

  26. self.layout.addWidget(start_button):将开始按钮添加到垂直布局中。

  27. self.layout.addWidget(pause_button):将暂停按钮添加到垂直布局中。

  28. self.setLayout(self.layout):将垂直布局设置为窗口的主布局。

  29. self.threads = [QThread() for _ in range(3)]:创建一个包含3个 QThread 的列表,用于处理多线程操作。

  30. self.workers = [Worker(i) for i in range(3)]:创建一个包含3个 Worker 的列表,每个 Worker 代表一个工作线程。

  31. for thread, worker, start_button, pause_button, progress_bar in zip(self.threads, self.workers, self.start_buttons, self.pause_buttons, self.progress_bars)::通过 zip 函数将线程、工作线程、开始按钮、暂停按钮和进度条进行配对。

  32. worker.moveToThread(thread):将每个 Worker 移动到相应的线程中。

  33. start_button.clicked.connect(worker.start_progress):连接开始按钮的点击信号到相应 Worker 的开始进度方法。

  34. pause_button.clicked.connect(worker.pause_progress):连接暂停按钮的点击信号到相应 Worker 的暂停进度方法。

  35. worker.update_progress_signal.connect(lambda value, pb=progress_bar: self.update_progress(pb, value)):连接工作线程的更新进度信号到主窗口的 update_progress 方法,以更新相应的进度条。

  36. thread.start():启动每个线程。

  37. self.setGeometry(300, 300, 300, 300):设置窗口的位置和大小。

  38. self.setWindowTitle('多线程进度条示例'):设置窗口的标题。

  39. self.show():显示窗口。

  40. def update_progress(self, progress_bar, value)::主窗口中用于更新进度条的方法。接收进度条和新的值,并将新值设置到相应的进度条上。

  41. progress_bar.setValue(value):设置进度条的当前值。

  42. 完整代码

  43. import sys
    from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal, QObject
    from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QProgressBar
    
    class Worker(QObject):
        update_progress_signal = pyqtSignal(int)
    
        def __init__(self, index):
            super().__init__()
            self.index = index
            self.progress_value = 0
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.update_progress)
    
        def start_progress(self):
            self.timer.start(100)
    
        def pause_progress(self):
            self.timer.stop()
    
        def update_progress(self):
            self.progress_value += 1
            if self.progress_value > 100:
                self.progress_value = 0
    
            self.update_progress_signal.emit(self.progress_value)
    
    class ProgressBarExample(QWidget):
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            self.progress_bars = [QProgressBar(self), QProgressBar(self), QProgressBar(self)]
            self.start_buttons = [QPushButton('开始', self), QPushButton('开始', self), QPushButton('开始', self)]
            self.pause_buttons = [QPushButton('暂停', self), QPushButton('暂停', self), QPushButton('暂停', self)]
    
            self.layout = QVBoxLayout()
    
            for progress_bar, start_button, pause_button in zip(self.progress_bars, self.start_buttons, self.pause_buttons):
                self.layout.addWidget(progress_bar)
                self.layout.addWidget(start_button)
                self.layout.addWidget(pause_button)
    
            self.setLayout(self.layout)
    
            self.threads = [QThread() for _ in range(3)]
            self.workers = [Worker(i) for i in range(3)]
    
            for thread, worker, start_button, pause_button, progress_bar in zip(
                    self.threads, self.workers, self.start_buttons, self.pause_buttons, self.progress_bars):
                worker.moveToThread(thread)
                start_button.clicked.connect(worker.start_progress)
                pause_button.clicked.connect(worker.pause_progress)
                worker.update_progress_signal.connect(lambda value, pb=progress_bar: self.update_progress(pb, value))
                thread.start()
    
            self.setGeometry(300, 300, 300, 300)
            self.setWindowTitle('多线程进度条示例')
            self.show()
    
        def update_progress(self, progress_bar, value):
            progress_bar.setValue(value)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = ProgressBarExample()
        sys.exit(app.exec_())
    

    本期的PyQt的程序案例就分享到这了!后期会更新更多PyQt的程序!感谢支持!有什么想看的程序在评论区留言!

  • 18
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RMB Player

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

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

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

打赏作者

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

抵扣说明:

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

余额充值