2017-05-27 87 views
0

我想构建一个使用简单的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

如何解决这个问题?

+0

你的例子中缺少了很多相关的代码。请提供[mcve]。 – ekhumoro

+0

@ekhumoro缺少什么?我会添加它。 – daegontaven

回答

0

我不确定,但如果GUI是主要部分,它必须先在其他线程之前启动。在GUI之前可能会发生一些或一种情况。检查这些出

+0

GUI首先启动。在main.py中有'self.ui.showMaximized()'行 – daegontaven

+0

你是否试过在数字大于一定数量的情况下分割数字 – IsaBostan

+0

这是一个解释器,所以它应该能够从一个线程完成。另外,你是什么意思分裂数字? – daegontaven