PyQt5 QThread问题

4

我正在尝试了解QT5线程的基础知识。这是我从各种来源组合而成的初次尝试:

import sys
from time import sleep

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout

from PyQt5.QtCore import QThread, QObject


'''

Traceback (most recent call last):
  File "threads.py", line 68, in <module>
    main(sys.argv)
  File "threads.py", line 63, in main
    window = Window()
  File "threads.py", line 15, in __init__
    self.initUi()
  File "threads.py", line 28, in initUi
    self.worker.moveToThread(self.thread)
AttributeError: 'NoneType' object has no attribute 'moveToThread'
Press any key to continue . . .

'''



class Window(QWidget):

    def __init__(self):

        super().__init__()
        self.initUi()

        self.low = 0
        self.high = 100

        self.show()


    def initUi(self):


        self.thread = QThread()
        self.worker = Worker(self)
        self.worker.moveToThread(self.thread)
        self.thread.start()

        self.button = QPushButton(
                'Start long running task')

        self.layout = QGridLayout()        
        self.layout.addWidget(self.button, 0, 0)

        self.setLayout(self.layout)



def Worker(QObject):

    def __init__(self, parent):
        super(Worker, self).__init__(parent)
        do_work()

    def do_work(self):

        for _ in range(20):
            print('running . . .')
            sleep(2)



def main(args):

    app = QApplication(args)
    window = Window()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main(sys.argv)

这里是我在代码片段中遇到的错误。

从在线文章中了解到,在PyQt5中,我不应该子类化QThread。

2个回答

4
你有两个问题,第一个问题是工作者必须是一个类才能进行更改:
def Worker(QObject):

to

class Worker(QObject):

另一个问题是,必须通过实例(即self)调用do_work才能进行更改:
do_work()

to:

self.do_work()

在接下来的部分中,我会展示一个完整的例子:
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout

from PyQt5.QtCore import QThread, QObject


class Window(QWidget):

    def __init__(self):

        super().__init__()
        self.initUi()

        self.low = 0
        self.high = 100

        self.show()


    def initUi(self):


        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)

        self.thread.started.connect(self.worker.do_work)
        self.thread.finished.connect(self.thread.deleteLater)

        self.button = QPushButton(
                'Start long running task')

        self.button.clicked.connect(self.thread.start)

        self.layout = QGridLayout()        
        self.layout.addWidget(self.button, 0, 0)
        self.setLayout(self.layout)



class Worker(QObject):
    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)

    def do_work(self):
        for _ in range(20):
            print('running . . .')
            QThread.sleep(2)



def main(args):

    app = QApplication(args)
    window = Window()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main(sys.argv)

哎呀,这些愚蠢的错误,简直不敢相信。非常感谢。 - Anonimista

0

在回顾QThreads时偶然发现了这个问题,真是惊人的快速遗忘能力,这就是为什么我要发布@ellyansec答案的升级版本,以便下次不必从头开始。我相信我停止QThreads的方式并不是最优的,请随意改进,这是我的代码:

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QGridLayout

from PyQt5.QtCore import QThread, QObject, pyqtSlot, pyqtSignal

import threading


class Window(QWidget):

    button_pushed = pyqtSignal()

    def __init__(self):

        super().__init__()
        self.initUi()

        self.low = 0
        self.high = 100

        self.show()

    def initUi(self):

        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)

        self.button_pushed.connect(self.worker.do_work)

        self.thread.finished.connect(self.thread.deleteLater)

        self.thread.start()

        self.button = QPushButton(
            'Start long running task')

        self.button_2 = QPushButton('Stop QThread')

        self.button.clicked.connect(self.start)

        self.button_2.clicked.connect(self.stop_thread)

        self.layout = QGridLayout()
        self.layout.addWidget(self.button, 0, 0)

        self.layout.addWidget(self.button_2, 50, 0)
        self.setLayout(self.layout)

        self.cnt = 0

    def start(self):

        self.cnt += 1

        print('button pushed ' + str(self.cnt) + '  time ')

        self.button_pushed.emit()

    def stop_thread(self):

        self.thread.quit()
        self.thread.wait()


class Worker(QObject):
    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)

    @pyqtSlot()
    def do_work(self):
        for k in range(3):
            print('running . . .' + str(threading.get_ident())+'.......'+str(k+1))
            QThread.sleep(2)

        print('done !!!')


def main(args):

    app = QApplication(args)
    window = Window()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main(sys.argv)



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接