You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PYQT5子线程接收服务端登录信号后操作UI窗口崩溃无响应问题

问题根因

PyQt的所有GUI控件操作必须在主线程(Qt事件循环所在线程)中执行,你当前的get_text函数运行在独立子线程中,直接在子线程调用MainWindow.show()、ChildWindow.close()、textBrowser.append()等UI操作,会触发线程安全问题导致程序无响应。

适配方案

用Qt自带的信号槽机制实现跨线程通信,子线程只负责接收数据发送信号,主线程接收信号后执行UI操作,具体修改如下(仅修改客户端代码):

步骤1:在Ui_MainWindow类中新增自定义信号

class Ui_MainWindow(QtWidgets.QMainWindow):
    # 新增自定义信号
    login_success = QtCore.pyqtSignal() # 登录成功信号
    new_message = QtCore.pyqtSignal(str, bytes) # 新消息信号,参数为消息内容、在线人数
    server_error = QtCore.pyqtSignal(str) # 服务端异常信号,参数为提示文案
    
    # 原有__init__、setupUi等代码保留

步骤2:在setupUi函数中绑定信号与槽函数

def setupUi(self):
    # 新增信号绑定逻辑
    self.login_success.connect(self.handle_login_success)
    self.new_message.connect(self.handle_new_message)
    self.server_error.connect(self.handle_server_error)
    
    # 原有代码全部保留
    self.cl = Client()
    # ...后面原有代码不需要改动

步骤3:新增主线程执行的UI操作槽函数

# 登录成功后UI操作
def handle_login_success(self):
    print("YOU GOT IN")
    MainWindow.show()
    ChildWindow.close()

# 收到新消息后UI操作
def handle_new_message(self, message, count_users):
    print("NOPE")
    print(f"message from server ---> {message}")
    self.pushButton_2.setEnabled(False)
    self.textBrowser.append(message)
    self.label_2.setText(f"Users in online: {count_users.decode('utf-8')}")

# 服务端异常后UI操作
def handle_server_error(self, tip):
    self.label_2.setText(tip)
    self.pushButton_2.setEnabled(False)

步骤4:修改get_text函数,移除直接UI操作改为发信号

def get_text(self):
    while True:
        try:
            data = self.cl.recv(2048)
            data = pickle.loads(data)
            print(data)
            if data[0] == "USER IS SIGN":
                # 发送登录成功信号即可,不要直接操作UI
                self.login_success.emit()
            else:
                message = data[1]
                count_users = data[0]
                # 发送新消息信号
                self.new_message.emit(message, count_users)
        except EOFError:
            print("EOFError")
            self.server_error.emit("!ВЫ ЗАПУСТИЛИ !")
            input()
        except Exception as err:
            print(err)
            self.server_error.emit("!SERVER STOPPED WORK!")
            input()

额外注意点

  1. 你当前用keyboard库实现的回车发消息逻辑也运行在子线程,后续如果需要在该逻辑中操作UI,同样需要用信号槽转发
  2. 服务端user_sign_in函数中登录失败分支的打印逻辑写错了,当前打印的还是USER IS SIGN,可自行修正

内容的提问来源于stack exchange,提问作者NIKITA76

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:15:06