问题描述
我正在制作迷你聊天应用程序,以提高我在 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_())