如何在非主线程中创建GUI小部件

时间:2019-03-11 14:17:50

标签: python sockets pyqt5

我有一个简单的服务器-客户端聊天程序,在其中我使用线程在后台从服务器接收数据。问题是当客户端收到消息时,必须为聊天创建一个新标签。但是我在线程中接收数据,因此可以检查数据并在线程中创建数据。因为我的窗口在主线程中,所以我无法创建窗口小部件并设置其父窗口。所以看起来像这样:

class MainWindow(QWidget):
    ...
        def addChatTab(self, nick, target, parent):
            tab = ChatTab(target)
            tab.setParent(parent)  #where I get the eror
            self.chatTabWidget.addTab(tab, nick)
            self.chatTabs[nick] = tab


class ServerManagement():
    ...
    def clientLoop(self): #runs in a different thread
        ...
        if sender == settingsManager.getUserNick():
            targetTab = receiver
        else:
            targetTab = sender

        if targetTab in mainWindow.chatTabs.keys():   #if tab is already there
            mainWindow.getChatTab(targetTab).write(message)
        else:
            mainWindow.addChatTab(targetTab, sender, mainWindow)     #create and add it to QTabWidget
            mainWindow.getChatTab(targetTab).write(message)

错误:

QObject::setParent: Cannot set parent, new parent is in a different thread

我了解这种情况的发生方式和原因,但我没有解决方案。有人可以帮我吗?

预先感谢...

1 个答案:

答案 0 :(得分:0)

您不应从另一个线程修改(理解也要创建)GUI,其想法是通过信号发送辅助线程的信息,因为它可以使ServerManagement从QObject继承,以便它可以创建信号并在ServerManagement对象和MainWindow之间建立连接的公共作用域:

class MainWindow(QWidget):
    # ...
    def addChatTab(self, nick, target, parent):
        tab = ChatTab(target)
        tab.setParent(parent)  #where I get the eror
        self.chatTabWidget.addTab(tab, nick)
        self.chatTabs[nick] = tab

    def foo_function(self, another_args)
       # ... foo function is the method where you create the Server Management object
       self.management = ServerManagement()
       self.management.targetChanged.connect(self.update_gui)
       #
    @pyqtSlot(str)
    def update_gui(self, targetTab):
        if targetTab in self.chatTabs.keys():   #if tab is already there
            self.getChatTab(targetTab).write(message)
        else:
            self.addChatTab(targetTab, sender, self)     #create and add it to QTabWidget
            self.getChatTab(targetTab).write(message)

class ServerManagement(QObject):
    targetChanged = pyqtSignal(str)
    def __init__(self, others_arguments):
        super(ServerManagement, self).__init__()
        # ...

    def clientLoop(self): #runs in a different thread
        # ...
        if sender == settingsManager.getUserNick():
            targetTab = receiver
        else:
            targetTab = sender
        self.targetChanged.emit(targetTab)