PyQt 线程完成并输出相同的消息两次

PyQt Thread Completes and outputs same message twice

我正在尝试创建一个带有进度条的 play/pause/resume/ 按钮。用户按下 'Start' 并且进度条初始化并填充 pause/resume 按钮。进度完成后,将打印一条消息并隐藏 pause/resume 按钮,同时再次显示 'Start' 按钮。但是,当我再次尝试 运行 'Start' 时,它会再次打印相同的完成消息。

如果我 运行 它两次,它会打印出两条完成消息。 运行 执行 3 次,打印 3 条完成信息等

from PyQt5.QtWidgets import (
        QWidget, QApplication, QProgressBar, QMainWindow,
        QHBoxLayout, QPushButton
    )
    
from PyQt5.QtCore import (
    Qt, QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool
)
import time


class WorkerSignals(QObject):
    progress = pyqtSignal(int)
    finished = pyqtSignal()

class JobRunner(QRunnable):
    
    signals = WorkerSignals()
    
    def __init__(self):
        super().__init__()
        
        self.is_paused = False
        self.is_killed = False
        
    @pyqtSlot()
    def run(self):
        for n in range(100):
            self.signals.progress.emit(n + 1)
            time.sleep(0.001)
            
            while self.is_paused:
                time.sleep(0)
                
            if self.is_killed:
                break
        self.signals.finished.emit()


    def finished(self):
        print('Finished')
                
    def pause(self):
        self.is_paused = True
        
    def resume(self):
        self.is_paused = False
        
    # def kill(self):


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        
        # Some buttons
        self.w = QWidget()
        self.l = QHBoxLayout()
        self.w.setLayout(self.l)
        
        self.btn_start = QPushButton("Start")

        
        self.l.addWidget(self.btn_start)

        
        self.setCentralWidget(self.w)
       
        # Create a statusbar.
        self.status = self.statusBar()
        self.progress = QProgressBar()
        self.status.addPermanentWidget(self.progress)
        
        # Thread runner
        # self.threadpool = QThreadPool()
        
        # # Create a runner
        # self.runner = JobRunner()
        # self.runner.signals.progress.connect(self.update_progress)
        # self.threadpool.start(self.runner)

        self.btn_start.pressed.connect(self.start_runner)
        # btn_pause.pressed.connect(self.runner.pause)
        # btn_resume.pressed.connect(self.runner.resume)
        

        # self.startTestSignal.connect(self.update_progress)

        self.show()
    
    def update_progress(self, n):
        self.progress.setValue(n)

    def start_runner(self):
        # Create ThreadPool
        self.threadpool = QThreadPool()
        self.threadpool.clear()
        # Create a runner
        self.runner = JobRunner()
        self.runner.signals.progress.connect(self.update_progress)

        self.threadpool.start(self.runner)
        self.progress.setValue(0)


        # Change Start Button to Pause
        self.btn_start.hide()

        # self.btn_start.setEnabled(False)

        self.btn_pause = QPushButton("Pause")
        self.btn_resume = QPushButton("Resume")
        self.l.addWidget(self.btn_pause)
        self.l.addWidget(self.btn_resume)

        self.btn_pause.pressed.connect(self.runner.pause)
        self.btn_resume.pressed.connect(self.runner.resume)
        self.runner.signals.finished.connect(self.check)


    def check(self):
        print('Thread Done')
        self.btn_start.show()
        self.progress.setValue(0)

        # self.runner.terminate()
        self.btn_pause.hide()
        self.btn_resume.hide()
        




        
app = QApplication([])
w = MainWindow()
app.exec_()

您正在创建 WorkerSignals 作为 class 属性,使其成为 class;所以当你这样做时:

    self.runner.signals.finished.connect(self.check)

您实际上正在将 再次 连接到 signals.finished,并且当您发出信号时,每次连接信号时都会调用函数 self.check

解决方案是将 WorkerSignals 创建为 实例 属性:

class JobRunner(QRunnable):
    def __init__(self):
        super().__init__()
        <b>self.signals = WorkerSignals()</b>
        self.is_paused = False
        self.is_killed = False