QThread:使用 GUI python 进行线程处理

问题描述

我正在制作迷你聊天应用程序,以提高我在 Python 中的套接字和 GUI 技能。但是每次启动应用程序时,我的 QThread 都在转储。 我需要用 GUI 运行线程 这是client.py

import socket
import sys
from colorama import Fore,Back,Style
from os import system,name
import sys
from chat import Ui_Form as Ui_Form
from login  import Ui_Form as Ui_Form1
from PyQt5 import QtCore,QtGui,QtWidgets
from threading import Thread

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

app = QtWidgets.QApplication(sys.argv)
Form_login = QtWidgets.QWidget()
ui_login = Ui_Form1()
ui_login.setupUi(Form_login)
Form_login.show()

Form_chat = QtWidgets.QWidget()
ui_chat = Ui_Form()
ui_chat.setupUi(Form_chat)
history = ''


class listen_thread(QtCore.QObject):
    running = False
    listen_var = QtCore.pyqtSignal(str)
    def run():
        print('checkpoint')
        while True:
            listen_var.emit('message')
            QtCore.QThread.msleep(1000)

def connect_pressed():
    username = ui_login.lineEdit.text()
    Form_login.hide()
    Form_chat.show()
    sock.connect(('127.0.0.1',10000))
    
    thread = QtCore.QThread()
    listen1 = listen_thread()
    listen1.moveToThread(thread)
    listen1.listen_var.connect(update_chat_history)
    thread.started.connect(listen1.run)
    thread.start()
    

@QtCore.pyqtSlot(str)
def update_chat_history(message):
    print(message)
    ui_chat.textEdit_2.append(message) 

def send_pressed():
    message = ui_login.lineEdit.text() + ' > ' + ui_chat.lineEdit.text()
    sock.send(bytes(str(message),'utf-8'))
    # update_chat_history(message)
    ui_chat.lineEdit.setText('')


def listen(some):
    while True:
        try:
            data = sock.recv(1024)
        except:
            pass
        else:
            update_chat_history(str(data))


ui_login.pushButton.clicked.connect(connect_pressed)
ui_chat.pushButton.clicked.connect(send_pressed)

sys.exit(app.exec_())

当我启动它时,输出是:

QThread: Destroyed while thread is still running
Aborted (core dumped)

有人可以帮忙吗???

解决方法

您的问题的解释很简单:在 connect_pressed 中创建的线程在该函数之外没有引用,因此一旦函数返回,它就会立即被垃圾回收。

“简单”的解决方案是在该函数之外创建线程并仅在那里运行线程,或者将线程添加到容器(例如,列表):

threads = []

def connect_pressed():
    # ...
    threads.append(thread)

但是,现实情况是,您的代码存在其他严重问题,一旦您尝试扩展代码,即使是最小限度,这些问题也可能会产生其他问题,这也是因为在使用 Qt 实现程序时,Qt 更容易处理子类;甚至 pyqtSlot 装饰器(通常是不必要的)只有在 QObject 子类的方法上设置时才能正确工作。

通常不鼓励仅使用匿名函数,因为它们不能直接引用必须使用的实例。此外,您的 run() 函数是错误的,因为它没有 self 参数,这会导致崩溃。

您的代码的更好版本可能类似于:

class LoginWindow(QtWidgets.QWidget,Ui_Form1):
    def __init__(self,listenThread):
        super().__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(listenThread.start)


class ChatWindow(QtWidgets.QWidget,Ui_Form):
    def __init__(self,listenThread,loginWindow):
        super().__init__()
        self.listenThread = listenThread
        self.loginWindow = loginWindow
        self.setupUi(self)
        self.listenThread.listen_var.connect(self.update_chat_history)

    def update_chat_history(self,message):
        print(message)
        self.textEdit_2.append(message) 

    def send_pressed(self):
        message = self.loginWindow.lineEdit.text() + ' > ' + self.lineEdit.text()
        sock.send(bytes(str(message),'utf-8'))
        self.lineEdit.setText('')


class ListenThread(QtCore.QThread):
    listen_var = QtCore.pyqtSignal(str)
    def run(self):
        print('checkpoint')
        while True:
            listen_var.emit('message')
            QtCore.QThread.msleep(1000)

listenThread = ListenThread()
loginWindow = LoginWindow(listenThread)
chatWindow = ChatWindow(listenThread,loginWindow)

sys.exit(app.exec_())

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...