2010-01-20 192 views
5

我正在尝试使用Python asyncore和pyqt4学习网络。QObject(QPlainTextEdit)&多线程问题

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

由于qts QApplication.exec_()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-功能,并且,使用的信号引起的纯函数调用的&槽代替可解决这个问题,但我也尝试过信号,我仍然得到这个错误。所以,(如果这真的是我的问题的原因)什么是从另一个线程调用qt对象的方法的正确方法是什么?

编辑更多信息: 的asyncore.loop()调用位于子线程,以及它不是一个真正阻挡,但只能在asyncore.loop的运行时间()我的服务器类(asyncore.dispatcher)可以做网络。 因此,在asyncore.loop()的运行时期间,我的Server类的方法被asyncore.loop()(= child thread)调用,并且在这些函数中我尝试向主线程中运行的窗口类发送信号

编辑:好像我现在工作,我的代码有一些错误,一切都按照预期的信号工作。

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

+0

你能发表一个解释或工作解决方案的片段吗?它肯定会在未来帮助其他人解决同样的问题。 =) – 2010-01-27 16:10:30

回答

8

看样子你正试图从非主线程的线程上访问QtGui类。就像其他一些GUI工具包(例如Java Swing)一样,这是不允许的。从Threads and QObjects网页:

尽管QObject的是折返,在GUI 类,特别是QWidget的及其所有子类 ,是不可重入。他们 只能从主线程使用。

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

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

+1

错误消息确实表明他尝试进行信号/插槽连接。但是,QTextBlock数据类型不是已注册的QMetaType,因此不能通过线程之间的连接来执行。 – e8johan 2010-01-21 07:00:27

+0

我完全忘了尝试QThread ...但我怎么能使用QThreads为我的问题??,因为QThreads'exec()_方法是一个阻塞方法再次,所以我不能运行它在像我的服务器类相同的线程。
@ e8johan:当我没有使用信号时,我得到了相同的错误信息。 – smerlin 2010-01-21 08:42:19