我想構建一個使用簡單的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