将参数传递给线程上的PyQt工作线程

2024-09-30 12:24:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力学习Python和PyQt,虽然它大部分都很好,但是我在PyQt线程方面遇到了一个巨大的问题。我已经使用Python“线程”模块很好地实现了这一点,尽管在occasion上我得到了Seg错误(没有额外的信息)。在

我想学习如何正确地使用PyQt进行线程化。我读过“你做错了”,“你没有做错那么多”,玛雅·波什的帖子,(蹩脚的)PyQt4和(稍微不那么蹩脚的)PyQt5文档,以及大量关于如何做到这一点的教程和示例(包括来自Stack-O的许多教程和示例),我越来越困惑了。在

我已经能够让线程启动一个Worker并完成它的工作并返回数据。我可以退出、发射等,没有问题,但是我不能将任何参数传递给Worker。我是个相当聪明的人,但这让我觉得自己是个十足的白痴!每次我读到新的东西并尝试它时,我都觉得我在试图把一个方形的木桩塞进一个圆孔里。在

我使用的是“moveToThread”特性,而不是对线程进行子类化,根据我读过的大多数帖子,这是正确的方法(尽管大多数示例都显示它是子类)。在

我不想听起来像个混蛋,但如果你能帮我解决这个问题,那么我需要的不仅仅是“当你说废话的时候就发过来”——我需要一个真实的例子或一些明确的东西。我见过有人接近回答这个问题,但他们是难以置信的含糊和Stack-O要求我有22个以上的声誉点,以便我评论或问别人的问题。。。~叹气

我有一个存根脚本,模仿我的大脚本。以下是存根中的相关代码:

def pre_Flight_Check():
    #count = 0 # I want to pass THIS to the Worker at Worker's start
    fire_Up_Thread(count)
#=====================
def butStop_click():
    # Stop Loop/Thread:
    flagQuit = flagQuit + 1
#=====================
# Worker:
class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    @pyqtSlot()
    def looper(self):
        flagQuit = 0
        count = 0 # I'd like to pass this into the Worker, not define it here
        while (count < 5):
            self.intCount.emit(count)
            time.sleep(1)
            count = count + 1
            if flagQuit != 0:
                break        
        self.finished.emit()
#========================
objWorker = Worker()
thrWorker = QThread()
#========================
# Threading stuffs:
def fire_Up_Thread(count):
    # NOTE: I CAN pass the "count" var into here, just not to the Worker
    objWorker.moveToThread(thrWorker)
    thrWorker.started.connect(objWorker.looper)
    objWorker.intCount.connect(updateTextBox)
    objWorker.finished.connect(thrWorker.quit)
    objWorker.finished.connect(work_finished)        
    # Start the thread:
    thrWorker.start()

仅供参考:这是使用Python线程的实现-非常简单和直接:

^{pr2}$

Tags: theto示例defcountconnectpass线程
2条回答

使用“functools”模块中的“partial”可以将变量视为可调用变量,然后可以使用该变量将参数传递给Worker。原话如下:

thrWorker.started.connect(objWorker.looper)

以及修改后的线条:

^{pr2}$

现在重新编写整个存根以合并更改:

def pre_Flight_Check():
    count = 0
    strIs = "is: " # NOTE: this is only here to show that more than 1 variable can be included
    fire_Up_Thread(count,strIs) # 2 vars to pass
#=====================
def butStop_click():
    flagQuit = flagQuit + 1
#=====================
# Worker:
class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    @pyqtSlot()
    def looper(self,count,strIs): # Both vars - "count" and "strIs"
        flagQuit = 0
        while (count < 5):
            strCount = "The count " + strIs + str(count)
            self.intCount.emit(count)
            time.sleep(1)
            count = count + 1
            # User clicked "Stop" button
            if flagQuit != 0:
                break
        self.finished.emit()
#========================
objWorker = Worker()
thrWorker = QThread()
#========================
# Threading stuffs:
def fire_Up_Thread(count,strIs): # Passed in from "pre_Flight_Check"
    from functools import partial
    objWorker.moveToThread(thrWorker)
    thrWorker.started.connect(partial(objWorker.looper,count,strIs)) # All vars are appended to connected target
    objWorker.intCount.connect(updateTextBox)
    objWorker.finished.connect(thrWorker.quit)
    objWorker.finished.connect(work_finished)
    # Start the thread:
    thrWorker.start()

这是有效的,它是线程安全的,它的速度很快,处理成本非常低。在

初始化Worker时只需传递参数

class Worker(QObject):
    finished = pyqtSignal()
    intCount = pyqtSignal(int)

    def __init__(self, count):
        super(Worker, self).__init__()
        self.count = count

    @pyqtSlot()
    def looper(self):
        flagQuit = 0
        while (self.count < 5):
            self.intCount.emit(self.count)
            time.sleep(1)
            self.count = self.count + 1
            if flagQuit != 0:
                break        
        self.finished.emit()


count = 0
objWorker = Worker(count)

相关问题 更多 >

    热门问题