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

QThread: Threading with 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 中创建的线程在该函数之外没有引用,因此一旦函数 returns.

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

threads = []

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

但是,现实情况是您的代码存在其他严重问题,一旦您尝试将代码扩展到最低限度,这些问题可能会立即产生其他问题,这也是因为 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_())