QObject (QPlainTextEdit) &多线程问题
我目前正在尝试使用 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 函数以及使用信号和函数引起的。插槽而不是普通函数调用可能会解决问题,但我也尝试过信号,但仍然收到此错误。
那么,(如果这确实是我的问题的原因)从另一个线程调用 qt 对象的方法的正确方法是什么?
编辑更多信息: asyncore.loop() 调用位于子线程中,它并不是真正阻塞,但只有在 asyncore.loop() 运行时我的服务器类(asyncore.dispatcher)才能进行网络连接。 因此,在 asyncore.loop() 运行时,我的 Server 类的方法由 asyncore.loop() (=子线程)调用,并且在这些方法中我 尝试向在主线程中运行的窗口类发出信号
编辑:似乎我现在可以正常工作了,我的代码中有一些错误,现在一切都按信号预期工作。
Im currently trying to learn Networking with Python asyncore and pyqt4.
I coded a small server, which basically listens on some port, and resends all messages it recieves to the sender.
Since both qts QApplication.exec_()
and asyncore.loop()
are functions which never return i could not start them both in one thread, so i stared asyncore.loop()
in a seperate daemon thread.
Whenever my server class (derived from asyncore.dispatcher
) establishes or drops a connection, or sends/recieves a message, it calls methods of my window class (derived from QtGui.QMainWindow
), which displays the information in a QPlainTextEdit
.
But the text is not visible, unless you mark the text with the mouse.
Python console displays following error msg:
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().)
I read on some forum, that this may be caused by calling qt-functions from another Thread, and that using signals & slots instead of plain function calling may fix the issue, but i have tried signals aswell, and i still get this error.
So, (if that is really the cause of my problems) whats the correct way to call methods of an qt object from another thread ?
EDIT More Info:
the asyncore.loop() call is located in the child thread, well its not really blocking, but only during the runtime of asyncore.loop() my Server class (asyncore.dispatcher) can do networking.
So, during the runtime of asyncore.loop() the methods of my Server class ARE called by asyncore.loop() (=child thread), and in these i
tried to emit signals to the window class running in the main thread
EDIT: Seems like i got it working now, i had some errors in my code, everything works as intended with signals now.
EDIT: small example: http://paste2.org/p/635612 (dead link)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来您正在尝试从主线程以外的线程访问 QtGui 类。与其他一些 GUI 工具包(例如 Java Swing)一样,这是不允许的。从 线程和 QObjects 网页:
解决方案是使用信号和槽在主线程(GUI 对象所在的位置)和辅助线程之间进行通信。基本上,您在一个线程中发出信号,然后通过另一线程传递到 QObject。我上面链接的页面对此进行了很好的讨论。实际上,Qt 中的线程支持 的整个部分都值得一读。
您可能遇到的一个潜在问题是,通常要获得跨线程工作的完整信号和槽支持,您需要使用 QThread::exec() 在子线程中启动事件循环(或者PyQt 等效项),以便可以将信号传递到位于其中的 QObject 中的插槽。就您而言,听起来您正在对 asyncore.loop() 进行阻塞调用,这将阻止您执行此操作。但是,如果您只需要向一个方向发出信号(从子线程到主线程中的小部件),我认为您不会遇到问题。
It appears you're trying to access QtGui classes from a thread other than the main thread. Like in some other GUI toolkits (e.g. Java Swing), that's not allowed. From the Threads and QObjects web page:
A solution is to use signals and slots for communication between the main thread (where the GUI objects live) and your secondary thread(s). Basically, you emit signals in one thread that get delivered to the QObjects via the other thread. The page I linked to above has a good discussion of this. Actually, the whole section on Thread Support in Qt is a good read.
One potential issue you could run into is that, normally, to get full signals and slots support working across threads, you need to start an event loop in the child thread using
QThread::exec()
(or the PyQt equivalent) so that signals can be delivered to slots in the QObjects that live there. In your case, it sounds like you're making a blocking call toasyncore.loop()
, which will prevent you from doing this. But, if you only need to emit signals in one direction (from the child thread to widgets in the main thread), I don't think you'll have a problem.