QObject(QPlainTextEdit)&多线程问题

时间:2010-01-20 20:40:00

标签: python multithreading qt4 pyqt4 asyncore

我目前正在尝试使用Python asyncore和pyqt4学习网络。

我编写了一个小型服务器,它基本上监听某个端口,并将收到的所有邮件重新发送给发件人。

由于qts QApplication.exec_()asyncore.loop()都是永不返回的函数,因此我无法在一个线程中启动它们,所以我在一个单独的守护程序线程中查看asyncore.loop()

每当我的服务器类(派生自asyncore.dispatcher)建立或删除连接,或发送/接收消息时,它都会调用我的窗口类(派生自QtGui.QMainWindow)的方法,该方法显示信息在QPlainTextEdit

但是文本不可见,除非您用鼠标标记文本。

Python控制台显示以下错误消息:

QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)

我在一些论坛上看到,这可能是由于从另一个线程调用qt-functions,以及使用信号&插槽而不是普通函数调用可以解决问题,但我也试过信号,我仍然得到这个错误。

所以,(如果那确实是我的问题的原因)是什么从另一个线程调用qt对象的方法的正确方法?

编辑更多信息: asyncore.loop()调用位于子线程中,它不是真正的阻塞,但只有在asyncore.loop()的运行时,我的Server类(asyncore.dispatcher)才能进行网络连接。 因此,在asyncore.loop()的运行时期间,我的Server类的方法由asyncore.loop()(=子线程)调用,并且在这些i中 试图向主线程中运行的窗口类发出信号

编辑:好像我现在正在使用它,我的代码中出现了一些错误,现在所有信号都按预期工作。

编辑:小例子:http://paste2.org/p/635612 (死链接)

1 个答案:

答案 0 :(得分:10)

您似乎正在尝试从主线程以外的线程访问QtGui类。与其他一些GUI工具包(例如Java Swing)一样,这是不允许的。来自Threads and QObjects网页:

  

虽然QObject是可重入的,但是GUI   类,尤其是QWidget及其所有   子类,不可重入。他们   只能在主线程中使用。

解决方案是使用信号和插槽在主线程(GUI对象所在的位置)和辅助线程之间进行通信。基本上,您在一个线程中发出信号,通过另一个线程传递给QObject。我上面链接的页面对此进行了很好的讨论。实际上,关于Thread Support in Qt的整个部分是一本很好的读物。

您可能遇到的一个潜在问题是,通常,要获得完整的信号和插槽支持跨线程工作,您需要使用QThread::exec()(或等效的PyQt)在子线程中启动事件循环,以便信号可以传递到生活在那里的QObject中的插槽。在你的情况下,听起来你正在对asyncore.loop()进行阻止调用,这会阻止你这样做。但是,如果你只需要在一个方向发射信号(从子线程到主线程中的小部件),我认为你不会有问题。