等待时间过长时 PyQt5 界面无响应
PyQt5 interface unresponsive when waiting too long
我正在使用 PyQt5 在 python 3.5 中为小型聊天机器人开发 GUI。我遇到的问题是预处理、post-处理和大脑花费太多时间来返回用户提供的输入的答案。
GUI 非常简单,如下所示:http://prntscr.com/dsxa39 加载速度非常快,无需连接到其他模块。我提到在收到大脑模块的回答之前使用睡眠仍然会使其无响应。
self.conversationBox.append("You: "+self.textbox.toPlainText())
self.textbox.setText("")
time.sleep(20)
self.conversationBox.append("Chatbot: " + "message from chatbot")
这是一小段代码示例,我需要修复它。
这是我遇到的错误:http://prnt.sc/dsxcqu
我提到我已经在所有地方搜索过我已经尝试过的解决方案,使用睡眠。但同样,这不会起作用,因为它也会使程序无响应。
慢速函数,例如 sleep
,将始终阻塞,除非它们在另一个线程中异步 运行。
如果您想避免线程,解决方法是分解慢速函数。在您的情况下,它可能看起来像:
for _ in range(20):
sleep(1)
self.app.processEvents()
其中 self.app
是对您的 QApplication 实例的引用。这个解决方案有点老套,因为它只会导致 20 次短挂而不是 1 次长挂。
如果你想将这种方法用于你的大脑功能,那么你将需要它以类似的方式分解它。除此之外,您还需要使用线程方法。
import sys
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QMainWindow, QGridLayout, QLabel, QApplication, QWidget, QTextBrowser, QTextEdit, \
QPushButton, QAction, QLineEdit, QMessageBox
from PyQt5.QtGui import QPalette, QIcon, QColor, QFont
from PyQt5.QtCore import pyqtSlot, Qt
import threading
import time
textboxValue = ""
FinalAnsw = ""
class myThread (threading.Thread):
print ("Start")
def __init__(self):
threading.Thread.__init__(self)
def run(self):
def getAnswer(unString):
#do brain here
time.sleep(10)
return unString
global textboxValue
global FinalAnsw
FinalAnsw = getAnswer(textboxValue)
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'ChatBot'
self.left = 40
self.top = 40
self.width = 650
self.height = 600
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
pal = QPalette();
pal.setColor(QPalette.Background, QColor(40, 40, 40));
self.setAutoFillBackground(True);
self.setPalette(pal);
font = QtGui.QFont()
font.setFamily("FreeMono")
font.setBold(True)
font.setPixelSize(15)
self.setStyleSheet("QTextEdit {color:#3d3838; font-size:12px; font-weight: bold}")
historylabel = QLabel('View your conversation history here: ')
historylabel.setStyleSheet('color: #82ecf9')
historylabel.setFont(font)
messagelabel = QLabel('Enter you message to the chat bot here:')
messagelabel.setStyleSheet('color: #82ecf9')
messagelabel.setFont(font)
self.conversationBox = QTextBrowser(self)
self.textbox = QTextEdit(self)
self.button = QPushButton('Send message', self)
self.button.setStyleSheet(
"QPushButton { background-color:#82ecf9; color: #3d3838 }" "QPushButton:pressed { background-color: black }")
grid = QGridLayout()
grid.setSpacing(10)
self.setLayout(grid)
grid.addWidget(historylabel, 1, 0)
grid.addWidget(self.conversationBox, 2, 0)
grid.addWidget(messagelabel, 3, 0)
grid.addWidget(self.textbox, 4, 0)
grid.addWidget(self.button, 5, 0)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.show()
def on_click(self):
global textboxValue
textboxValue = self.textbox.toPlainText()
self.conversationBox.append("You: " + textboxValue)
th = myThread()
th.start()
th.join()
global FinalAnsw
self.conversationBox.append("Rocket: " + FinalAnsw)
self.textbox.setText("")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
app.exec_()
所以创建一个简单的线程解决了这个问题,上面的代码仍然会因为睡眠函数调用而冻结,但是如果你用一个持续很长时间的普通函数替换它,它就不会再冻结了。通过我的项目的大脑模块测试了它们的功能。
有关构建线程的简单示例,请使用 https://www.tutorialspoint.com/python/python_multithreading.htm
对于 PyQt GUI,我使用本网站的示例来学习 http://zetcode.com/gui/pyqt5/
我正在使用 PyQt5 在 python 3.5 中为小型聊天机器人开发 GUI。我遇到的问题是预处理、post-处理和大脑花费太多时间来返回用户提供的输入的答案。
GUI 非常简单,如下所示:http://prntscr.com/dsxa39 加载速度非常快,无需连接到其他模块。我提到在收到大脑模块的回答之前使用睡眠仍然会使其无响应。
self.conversationBox.append("You: "+self.textbox.toPlainText())
self.textbox.setText("")
time.sleep(20)
self.conversationBox.append("Chatbot: " + "message from chatbot")
这是一小段代码示例,我需要修复它。
这是我遇到的错误:http://prnt.sc/dsxcqu
我提到我已经在所有地方搜索过我已经尝试过的解决方案,使用睡眠。但同样,这不会起作用,因为它也会使程序无响应。
慢速函数,例如 sleep
,将始终阻塞,除非它们在另一个线程中异步 运行。
如果您想避免线程,解决方法是分解慢速函数。在您的情况下,它可能看起来像:
for _ in range(20):
sleep(1)
self.app.processEvents()
其中 self.app
是对您的 QApplication 实例的引用。这个解决方案有点老套,因为它只会导致 20 次短挂而不是 1 次长挂。
如果你想将这种方法用于你的大脑功能,那么你将需要它以类似的方式分解它。除此之外,您还需要使用线程方法。
import sys
from PyQt5 import QtCore, QtGui
from PyQt5.QtWidgets import QMainWindow, QGridLayout, QLabel, QApplication, QWidget, QTextBrowser, QTextEdit, \
QPushButton, QAction, QLineEdit, QMessageBox
from PyQt5.QtGui import QPalette, QIcon, QColor, QFont
from PyQt5.QtCore import pyqtSlot, Qt
import threading
import time
textboxValue = ""
FinalAnsw = ""
class myThread (threading.Thread):
print ("Start")
def __init__(self):
threading.Thread.__init__(self)
def run(self):
def getAnswer(unString):
#do brain here
time.sleep(10)
return unString
global textboxValue
global FinalAnsw
FinalAnsw = getAnswer(textboxValue)
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'ChatBot'
self.left = 40
self.top = 40
self.width = 650
self.height = 600
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
pal = QPalette();
pal.setColor(QPalette.Background, QColor(40, 40, 40));
self.setAutoFillBackground(True);
self.setPalette(pal);
font = QtGui.QFont()
font.setFamily("FreeMono")
font.setBold(True)
font.setPixelSize(15)
self.setStyleSheet("QTextEdit {color:#3d3838; font-size:12px; font-weight: bold}")
historylabel = QLabel('View your conversation history here: ')
historylabel.setStyleSheet('color: #82ecf9')
historylabel.setFont(font)
messagelabel = QLabel('Enter you message to the chat bot here:')
messagelabel.setStyleSheet('color: #82ecf9')
messagelabel.setFont(font)
self.conversationBox = QTextBrowser(self)
self.textbox = QTextEdit(self)
self.button = QPushButton('Send message', self)
self.button.setStyleSheet(
"QPushButton { background-color:#82ecf9; color: #3d3838 }" "QPushButton:pressed { background-color: black }")
grid = QGridLayout()
grid.setSpacing(10)
self.setLayout(grid)
grid.addWidget(historylabel, 1, 0)
grid.addWidget(self.conversationBox, 2, 0)
grid.addWidget(messagelabel, 3, 0)
grid.addWidget(self.textbox, 4, 0)
grid.addWidget(self.button, 5, 0)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.show()
def on_click(self):
global textboxValue
textboxValue = self.textbox.toPlainText()
self.conversationBox.append("You: " + textboxValue)
th = myThread()
th.start()
th.join()
global FinalAnsw
self.conversationBox.append("Rocket: " + FinalAnsw)
self.textbox.setText("")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
app.exec_()
所以创建一个简单的线程解决了这个问题,上面的代码仍然会因为睡眠函数调用而冻结,但是如果你用一个持续很长时间的普通函数替换它,它就不会再冻结了。通过我的项目的大脑模块测试了它们的功能。
有关构建线程的简单示例,请使用 https://www.tutorialspoint.com/python/python_multithreading.htm
对于 PyQt GUI,我使用本网站的示例来学习 http://zetcode.com/gui/pyqt5/