从线程启动一个函数。 (GUI 线程和 QThread 错误)
Start a function from a thread. (GUI thread and QThread errors)
我已经使用 Python 的线程模块将例程变为 运行 子进程并等待它完成。
我使用以下行进行线程处理:
t1=Thread(target=self.routineFunction, args=(self, "file1.txt", "file2.txt", self.nextFunction)).start()
在我的函数 routineFunction(self,file1,file2,nextFunction) 中,一旦子进程完成 运行ning.
,我将下一个函数调用到 运行
在那之前一切正常。
但是如果我在下一个函数中创建新的 QObject 项,我会收到很多错误:
- "QPixmap: It is not safe to use pixmaps outside the GUI thread"
- "QObject::startTimer: QTimer can only be used with threads started with QThread"
我的猜测是,当我从例程中调用 nextFunction 时,它 运行 在与例程相同的线程中,因此出现错误。
有没有办法从 "main" 或 "normal" 线程中的例程调用函数?
感谢您的帮助。
一般从其他线程调用函数是可以的。但是许多 GUI 库(其中包括 QT)对此行为有一些限制。
例如,有一个名为 'GUI thread' 的指定线程,它处理所有图形内容,例如从 OS 发送消息、重绘 windows 等。您还限制使用具有此唯一线程的 GUI。因此,例如,您不应在其他线程中创建 QPixmap
。
QTimer
使用一些 QThread
的内部数据,所以你应该在只以 QThread
开始的线程中使用这样的计时器,而不是普通的 Python thread
模块。
回到您的问题,如果您想使用 QT,您应该使用 QThread
和 post 事件将线程生成到使用 postEvent()
方法的 GUI 线程。这将确保 QT 内部数据结构的一致性。
因此,您可以在任何 QT 线程中 运行 您的代码,但是如果您想使用 GUI(您的 QObject
使用 QPixmap
,情况就是这样),您只需要在 GUI 线程中处理此类调用。
好的,所以我认为 werewindle 解决方案是可行的。不幸的是,我发现很难将我当前的脚本从 Thread 转换为 QThread(我通常是线程的新手)。
我找到了解决方法:
我没有将 nextFunction 作为参数传递,而是传递了一个 queue = Queue.Queue() 并在我的新线程中的子进程成功时使用 queue.put(True) 。没有更多的 nextFunction,我只是用 queue.get() 等待队列中的值。
通过这样做,我可以在 GUI 线程中继续。
我已经使用 Python 的线程模块将例程变为 运行 子进程并等待它完成。 我使用以下行进行线程处理:
t1=Thread(target=self.routineFunction, args=(self, "file1.txt", "file2.txt", self.nextFunction)).start()
在我的函数 routineFunction(self,file1,file2,nextFunction) 中,一旦子进程完成 运行ning.
,我将下一个函数调用到 运行在那之前一切正常。
但是如果我在下一个函数中创建新的 QObject 项,我会收到很多错误: - "QPixmap: It is not safe to use pixmaps outside the GUI thread" - "QObject::startTimer: QTimer can only be used with threads started with QThread"
我的猜测是,当我从例程中调用 nextFunction 时,它 运行 在与例程相同的线程中,因此出现错误。 有没有办法从 "main" 或 "normal" 线程中的例程调用函数?
感谢您的帮助。
一般从其他线程调用函数是可以的。但是许多 GUI 库(其中包括 QT)对此行为有一些限制。
例如,有一个名为 'GUI thread' 的指定线程,它处理所有图形内容,例如从 OS 发送消息、重绘 windows 等。您还限制使用具有此唯一线程的 GUI。因此,例如,您不应在其他线程中创建 QPixmap
。
QTimer
使用一些 QThread
的内部数据,所以你应该在只以 QThread
开始的线程中使用这样的计时器,而不是普通的 Python thread
模块。
回到您的问题,如果您想使用 QT,您应该使用 QThread
和 post 事件将线程生成到使用 postEvent()
方法的 GUI 线程。这将确保 QT 内部数据结构的一致性。
因此,您可以在任何 QT 线程中 运行 您的代码,但是如果您想使用 GUI(您的 QObject
使用 QPixmap
,情况就是这样),您只需要在 GUI 线程中处理此类调用。
好的,所以我认为 werewindle 解决方案是可行的。不幸的是,我发现很难将我当前的脚本从 Thread 转换为 QThread(我通常是线程的新手)。
我找到了解决方法: 我没有将 nextFunction 作为参数传递,而是传递了一个 queue = Queue.Queue() 并在我的新线程中的子进程成功时使用 queue.put(True) 。没有更多的 nextFunction,我只是用 queue.get() 等待队列中的值。 通过这样做,我可以在 GUI 线程中继续。