我有3个课程
一个是控制台类:
class Console(QWidget):
def __init__(self):
super().__init__()
self.editor = QPlainTextEdit(self)
self.editor.setReadOnly(True)
self.font = QFont()
self.font.setFamily(editor["editorFont"])
self.font.setPointSize(12)
self.layout = QVBoxLayout()
self.layout.addWidget(self.editor, 1)
self.setLayout(self.layout)
self.output = None
self.error = None
self.editor.setFont(self.font)
def run(self, command):
"""Executes a system command."""
out, err = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
self.output = out
self.error = err
self.editor.setPlainText((self.output + self.error).decode())
return self.output + self.error
另一个是Tabs类,它将Console()赋给变量self.console
然后我有了Main类,它具有一个名为Terminal的功能,可以通过键盘快捷键Shift + F10来调用
这将使用打开的文件的当前文件名(由Tabs类处理),并使用子进程运行它。
现在,当运行一些不是即时的程序时,我们就可以解决问题了,
整个gui死机了,当Console类执行run
函数时,我不知道如何使GUI响应
完整代码可在此处找到:https://github.com/Fuchsiaff/PyPad
答案 0 :(得分:2)
您不使用subprocess.Popen()
是因为它正在阻塞,并且阻塞任务的缺点之一是它们不允许GUI执行其他作业,因为此Qt提供了QProcess
类不会阻止事件循环:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Console(QtWidgets.QWidget):
errorSignal = QtCore.pyqtSignal(str)
outputSignal = QtCore.pyqtSignal(str)
def __init__(self):
super().__init__()
self.editor = QtWidgets.QPlainTextEdit(self)
self.editor.setReadOnly(True)
self.font = QtGui.QFont()
# self.font.setFamily(editor["editorFont"])
self.font.setPointSize(12)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.editor, 1)
self.setLayout(self.layout)
self.output = None
self.error = None
self.editor.setFont(self.font)
self.process = QtCore.QProcess()
self.process.readyReadStandardError.connect(self.onReadyReadStandardError)
self.process.readyReadStandardOutput.connect(self.onReadyReadStandardOutput)
def onReadyReadStandardError(self):
error = self.process.readAllStandardError().data().decode()
self.editor.appendPlainText(error)
self.errorSignal.emit(error)
def onReadyReadStandardOutput(self):
result = self.process.readAllStandardOutput().data().decode()
self.editor.appendPlainText(result)
self.outputSignal.emit(result)
def run(self, command):
"""Executes a system command."""
# clear previous text
self.editor.clear()
self.process.start(command)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Console()
w.show()
w.errorSignal.connect(lambda error: print(error))
w.outputSignal.connect(lambda output: print(output))
w.run("ping 8.8.8.8 -c 100")
sys.exit(app.exec_())
答案 1 :(得分:-2)
使用python的内置线程模块。
然后做:
import threading
用作:
def run(self, command):
"""Executes a system command."""
tt = threading.Threading( target = self._sub_thread )
tt.start()
def _sub_thread(self):
out, err = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
self.output = out
self.error = err
self.editor.setPlainText((self.output + self.error).decode())
这是实用的