简体   繁体   English

PyQt5 QThread 既不终止也不终止或标志变量

[英]PyQt5 QThread does not stop neither with terminate or a flag variable

Hi I am developing a PyQt5 Application where the user can set a timer countdown.您好我正在开发一个 PyQt5 应用程序,用户可以在其中设置计时器倒计时。 For updating the time label I use a QThread which emits a pyqtSignal every second in order to update the GUI/time label.为了更新时间 label,我使用 QThread 每秒发出一个 pyqtSignal 以更新 GUI/时间 label。 This is my Code which uses QThread:这是我使用 QThread 的代码:

from PyQt5.QtCore import QThread, pyqtSignal, QObject import time from PyQt5.QtCore import QThread, pyqtSignal, QObject 导入时间

class Worker(QObject):
    update = pyqtSignal()
    stop = pyqtSignal()


class CountdownThread(QThread):
    def __init__(self, time_left):
        QThread.__init__(self)
        self.time_signal = Worker()
        self.time_left = time_left
        self.is_running = True


    def stop(self):
        self.is_running = False
        print(self.is_running)


    def run(self):
        while self.is_running:
            self.time_left -= 1
            time.sleep(1)
            self.time_signal.update.emit()
            if self.time_left == 0:
                self.stop()

With a button click the user should be able to stop the countdown and reset the GUI:通过单击按钮,用户应该能够停止倒计时并重置 GUI:

...

    def pressed_stop(self):
        self.start_stop_btn.setText("Start")
        self.start_stop_btn.clicked.connect(self.pressed_start)
        self.worker.stop() # self.worker is the QThread

...

When I click on the button the button text certainly does change to "Start".当我单击按钮时,按钮文本肯定会更改为“开始”。 But the time label keeps counting down.但是时间label一直倒计时。 Printing the is_running variable prints out False when clicking the button and therefore executing the self.worker.stop() function but keeps printing out True in the while loop of run() .单击按钮并因此执行self.worker.stop() function 时打印is_running变量会打印出False ,但会在run()while循环中继续打印出True

Initializing the CountdownThread is done here (after clicking start button):初始化CountdownThread在这里完成(点击开始按钮后):

...

    def count_down(self):
        self.worker = CountdownThread(self.time_left)
        self.worker.time_signal.update.connect(self.update_time_label)
        self.worker.time_signal.stop.connect(self.reset_timer)
        self.worker.start()

...

Why doesn't this work?为什么这不起作用? I am running this application on Mac OS Catalina 10.15.4.我在 Mac OS Catalina 10.15.4 上运行这个应用程序。

As some might have noticed, I am using the same button object for starting and stopping the countdown.有些人可能已经注意到,我使用同一个按钮 object 来启动和停止倒计时。 I forgot to add我忘了添加

self.start_stop_btn.disconnect()

otherwise it would always call the countdown function again否则它总是会再次调用倒计时 function

The thing happening here is that your QThread spends all of its time in a while(True) loop, therefore it can never execute its stop() method before reaching the end of the countdown by the loop.这里发生的事情是您的 QThread 将所有时间都花在了while(True)循环中,因此它永远无法在循环到达倒计时结束之前执行其stop()方法。

I think a similar thread exists that adresses the same question.我认为存在一个类似的线程来解决相同的问题。

What you can do to circumvent the issue is to include in your loop a way to fetch the stop flag from your main thread.你可以做些什么来规避这个问题是在你的循环中包含一种从你的主线程中获取停止标志的方法。

A few recommendations:一些建议:

  • Don't name a variable "worker" if you have a class named Worker: it's confusing如果您有一个名为 Worker 的 class,请不要将变量命名为“worker”:这很混乱
  • Instead of using time.sleep(xx) , I advise you to use QTimers for your application: they do the same but in a much easier way, and that would get rid of the while loop.我建议您不要使用 time.sleep time.sleep(xx) ,而是将 QTimers 用于您的应用程序:它们的作用相同,但方式更简单,并且可以摆脱 while 循环。
  • It is best practice to use signals and slots to communicate between threads (needed anyway for QTimer usage).最佳实践是使用信号和槽在线程之间进行通信(无论如何都需要使用 QTimer)。 Using them can get you through the while loop depending on the connection type (as it uses the event loop for QueuedConnection).根据连接类型,使用它们可以让您通过 while 循环(因为它使用 QueuedConnection 的事件循环)。
  • Although having a class that inherits from QThread works, it is recommended to create a classical QThread, have your tasks written in another class which extends QObject, then use the_QObject_extended_variable.moveToThread(the_QThread_variable)虽然有一个继承自 QThread 的 class 工作,但建议创建一个经典的 QThread,将您的任务写入另一个扩展 QObject 的 class,然后使用the_QObject_extended_variable.moveToThread(the_QThread_variable)

Feel free to ask for examples if you need.如果您需要,请随时询问示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM