10

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

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

由于 qtsQApplication.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() 运行时,我的服务器类 (asyncore.dispatcher) 才能进行联网。因此,在 asyncore.loop() 运行时,我的服务器类的方法由 asyncore.loop() (=子线程)调用,在这些方法中,我尝试向在主线程中运行的窗口类发出信号

编辑:好像我现在可以正常工作了,我的代码中有一些错误,现在一切都按预期工作。

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

4

1 回答 1

14

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

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

一种解决方案是使用信号和槽在主线程(GUI 对象所在的位置)和辅助线程之间进行通信。基本上,您在一个线程中发出信号,然后通过另一个线程传递给 QObjects。我上面链接的页面对此进行了很好的讨论。实际上, Qt 中有关线程支持的整个部分都值得一读。

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

于 2010-01-20T21:09:55.310 回答