2017-05-27 60 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