2011-11-25 165 views
0

我正在開發一個聊天程序,其中客戶端是單線程的,但服務器將爲每個連接的客戶端啓動一個新線程。我相信我的客戶端代碼是穩定的,但服務器讓我感到困惑。如何從QThread啓動GUI窗口?

現在,我有一個派生的QTcpSocket類查找傳入連接,當它看到一個,開始一個新的QThread。當QThread運行時,它會創建一個QMainWindow(它是聊天窗口)的實例並顯示它。

void secureserver::incomingConnection(int socketDescriptor) 
{ 
    securethread *thread = new securethread(socketDescriptor, this); 
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
    thread->start(); 
} 

void securethread::run() 
{ 
    serverwindow myServerWindow; 
    myServerWindow.setSocketDescriptor(mySocket); 
    myServerWindow.show(); 
} 

我已經得到錯誤stderror像下面,和QMainWindow永遠不會出現這樣聊着在這一點上是不可能的。

QObject: Cannot create children for a parent that is in a different thread. 
(Parent is QApplication(0xbf9e5358), parent's thread is QThread(0x98a54f0), current thread is securethread(0x99e9250) 
QPixmap: It is not safe to use pixmaps outside the GUI thread 

我的問題是:

  • 我需要做的QThreadQMainWindow父母?
  • 我是以完全錯誤的方式去談論這個嗎?
  • 任何其他一般的想法,爲什麼這不工作,因爲我期望它 或如何解決它將不勝感激。
+0

我很困惑,爲什麼你的服務器有任何GUI代碼在所有。在我看來,你的客戶端應該是顯示聊天窗口的客戶端,而服務器應該是純粹的將消息從一個客戶端傳遞到另一個客戶端的機制。 – Chris

+0

這個想法是,你有許多客戶端,一臺服務器(一個本地IP地址和端口),但服務器爲每個傳入連接創建一個新線程。然後,服務器可以在每個窗口中僅有一個客戶端進行通信,但它可以同時在這些新線程/窗口中發送/接收,因爲它們將處於其自己的線程中。我沒有設計這個程序的規格,所以我和你一起問爲什麼。 – J2N

回答

1

是的,你正在以錯誤的方式去解決這個問題。由於平臺限制,GUI是單線程系統。你不能在不同的線程上創建,更改和管理GUI對象 - 一切都必須在一個線程上完成(通常是GUI線程)。

Qt有兩種處理工作線程和GUI的機制:排隊信號和插槽,以及QCoreApplication :: postEvent()處理程序。

更多詳情,全面Qt的線程文件:http://doc.qt.io/qt-5/thread-basics.html

+0

嗯,你有什麼建議爲每個傳入的客戶端連接打開一個新窗口嗎? 這是對服務器是多線程的項目的一個要求,並且每個試圖聊天的客戶端都會彈出一個新的聊天窗口,以便多個客戶端可以同時與服務器進行通信。 – J2N

+0

@JLaw:線程可以處理I/O和消息,但是所有的GUI活動都需要在一個線程上完成。您應該使用排隊信號/插槽機制與UI進行通信,而不是混合服務器代碼和UI代碼。 –

+0

這很有道理,我可以使用信號和插槽。我仍然唯一想知道的是,我需要爲每個客戶端單獨彈出一個窗口。我仍然可以使用我的incomingConnection函數來創建GUI窗口和線程的新實例,並使用該線程和窗口之間的信號/插槽? – J2N