2015-05-19 179 views
0

我已经用Python的线程模块做了例程来运行一个子进程并等待它完成。 我做穿线用下面一行:从一个线程启动一个函数。 (GUI线程和QThread错误)

t1=Thread(target=self.routineFunction, args=(self, "file1.txt", "file2.txt", self.nextFunction)).start() 

在我的功能routineFunction(自我,文件1,文件2,nextFunction)我叫下一个功能,一旦子进程运行完毕后才能运行。

一切工作正常,直到那时。

但是如果我在我的下一个函数来创建新的QObject的项目,我收到了很多的错误: - “的QPixmap:这不是安全使用GUI线程之外的像素图” - “的QObject :: startTimer所:QTimer能只能使用线程开始的QThread”

我的猜测是,当我打电话nextFunction从常规它在同一个线程的程序中,因此错误的跑了。 有没有办法从“main”或“normal”线程中的例程调用一个函数?

谢谢你的帮助。

+0

使用qt线程代替python线程,并在worker完成时发出信号。 – ekhumoro

回答

2

一般来说,它是好的从其他线程调用函数。但是许多GUI库(QT就在其中)对这种行为有一些限制。

例如,有一个叫做'GUI线程'的指定线程,它处理所有图形的东西,比如从OS调度消息,重绘窗口等。而且你也限制使用这个唯一线程来处理GUI。因此,例如,您不应在其他线程中创建QPixmap

QTimer使用一些QThread的内部数据,所以你应该使用只在开始QThread螺纹,定时器,但与普通的Python thread模块。

回到你的问题,如果你想使用QT工作,你应该使用QThread产生你的线程,并使用postEvent()方法将事件发布到GUI线程。这将保证QT内部数据结构的一致性。因此,你可以在任何QT线程中运行你的代码,但是如果你想使用GUI(你的QObject使用QPixmap,所以情况是这样),你只需要在GUI线程中处理这种调用。

+0

感谢您的好解释。我将尝试使用此QThread和postEvent()返回到GUI线程 –

0

好了,所以我认为werewindle的解决方案是可能的。不幸的是,我发现很难将当前的脚本从Thread转换为QThread(我通常是新线程)。

我找到了一个解决方法: 而不是传递nextFunction作为参数,我传递队列= Queue.Queue()和我使用queue.put(True)如果我的新线程中的子进程是成功的。没有更多的nextFunction,我只需使用queue.get()等待队列中的值。 通过这样做,我可以继续在GUI线程中。