我想构建一个使用简单的QTextEdit的自定义Python控制台小部件。行编辑框接收输入并通过线程中的python解释器运行它。即使使用QThreadPool,GUI为什么会冻结?
这里是interpreter.py
import sys
from io import StringIO, IncrementalNewlineDecoder
from code import InteractiveConsole
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
from stream import NewLineIO
class PythonInterpreter(QObject, InteractiveConsole):
output = pyqtSignal(str)
def __init__(self):
QObject.__init__(self)
self.l = {}
InteractiveConsole.__init__(self, self.l)
self.out = NewLineIO()
self.out.output.signal_str.connect(self.console)
def write(self, string):
self.output.emit(string)
def runcode(self, codez):
"""
Reimplementation to capture stdout and stderr
"""
sys.stdout = self.out
sys.stderr = self.out
sys.excepthook = sys.__excepthook__
result = InteractiveConsole.runcode(self, codez) # Where the magic happens
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
#self.output.emit(self.out.getvalue()) # Send the output
return result
@pyqtSlot(str)
def console(self, string):
#print(string, file=sys.__stdout__)
self.output.emit(string)
class JavaScriptInterpreter(QObject):
pass
这是main.py
import sys
from traceback import TracebackException
from PyQt5 import QtCore, uic
from PyQt5.QtCore import QThread, QThreadPool
from PyQt5.QtGui import QFont, QColor
from PyQt5.QtWidgets import (QApplication, QDialog,
QAction)
from PyQt5.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs
from interpreters import PythonInterpreter
from lexers import PythonLexer
from threads import Worker, WorkerSignals
from stream import NewLineIO
class MainWindow(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.ui = uic.loadUi("main.ui")
self.ui.showMaximized()
# Code Editor
self.font = QFont()
self.font.setFamily('Courier New')
self.font.setFixedPitch(True)
self.font.setPointSize(10)
self.ui.code_editor.setFont(self.font)
self.lexer = PythonLexer(self.ui, self.font)
self.lexer.lock()
# Console
self.interpreter = PythonInterpreter()
self.ui.console_log.isReadOnly()
self.ui.console_input.returnPressed.connect(self.send_console_input)
self.interpreter.output.connect(self.send_console_log)
# Threads
self.threadpool = QThreadPool()
def send_console_input(self):
command = self.ui.console_input.text()
self.ui.console_input.clear()
worker = Worker(self.interpreter.push, str(command))
worker.signals.result.connect(print)
worker.signals.finished.connect(self.thread_complete)
#self.interpreter.push(str(command))
self.threadpool.start(worker)
print("Thread Count: ",
self.threadpool.activeThreadCount(),
file=sys.__stdout__)
def thread_complete(self):
print("Thread Complete !")
def send_console_log(self, command):
print(command, file=sys.__stdout__)
self.ui.console_log.append(command)
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
的每次从PythonInterpreter
实例的信号被发射它调用self.send_console_log
其接收从该命令的输出在翻译上运行。
但是,如果我通过self.send_console_input
运行一个大圈像for i in range(10000):print(i)
是送往解释的命令时,它会做print语句中self.send_console_log
罚款,但不是.append()
。它会冻结,直到循环完成,整个事情将被追加到QTextEdit
。
如何解决这个问题?
你的例子中缺少了很多相关的代码。请提供[mcve]。 – ekhumoro
@ekhumoro缺少什么?我会添加它。 – daegontaven