2010-01-20 39 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