我做了很多研究,但我没有找到一个好的解决方案。 我想创建一个具有小区域的Gui,我可以在其中启动外部程序并在文本区域中实时显示其输出。该程序是控制台应用程序。另外,我必须有可能在任何时候停止它(开始/停止/重新开始)。
答案 0 :(得分:1)
一个示例,其中一个线程输出第二个窗口并在主窗口中输出流的结果。 该计划文本中的评论:
import random
from PyQt5 import Qt
class WorkThread(Qt.QThread):
''' Streaming task in its window.
Signals and Slots are used for communication between objects. '''
# Declare a signal, with an argument (int) for transmission in the connected slots
threadSignal = Qt.pyqtSignal(int)
def __init__(self, startParm):
super().__init__()
self.startParm = startParm # Initialize the parameters passed to the task
def run(self, *args, **kwargs):
c = self.startParm
while True:
Qt.QThread.msleep(200)
c += 1
self.threadSignal.emit(c) # We disable the signal and pass arguments to the connected slot
class WorkThreadMain(Qt.QThread):
''' Streaming Main task '''
threadSignalMain = Qt.pyqtSignal(int)
def __init__(self, startParm):
super().__init__()
self.startParm = startParm
def run(self, *args, **kwargs):
c = self.startParm
while True:
Qt.QThread.msleep(1000)
c += 1
self.threadSignalMain.emit(c)
class MsgBox(Qt.QDialog):
""" Window initialization class for visualizing an additional stream
and a button to close the stream window if the thread is stopped! """
def __init__(self):
super().__init__()
layout = Qt.QVBoxLayout(self)
self.label = Qt.QLabel("")
layout.addWidget(self.label)
close_btn = Qt.QPushButton("Close thread")
layout.addWidget(close_btn)
close_btn.clicked.connect(self.close)
self.setGeometry(900, 65, 400, 80)
self.setWindowTitle('MsgBox for WorkThread')
class MainWindow(Qt.QWidget):
''' Main Window '''
def __init__(self):
super().__init__()
layout = Qt.QVBoxLayout(self)
self.labelMain = Qt.QLabel("The result of the Main task: ")
layout.addWidget(self.labelMain)
self.labelThread = Qt.QLabel("The result of the Thread task: ")
layout.addWidget(self.labelThread)
validator = Qt.QIntValidator(1, 999, self)
validator.setBottom(1)
self.lineEdit = Qt.QLineEdit()
self.lineEdit.setPlaceholderText("Enter the initial parameter for the stream task")
self.lineEdit.setValidator(validator) # self.lineEdit will only take integers from 1 to 999
layout.addWidget(self.lineEdit)
self.btn = Qt.QPushButton("Start thread!")
layout.addWidget(self.btn)
self.btnMain = Qt.QPushButton("Start Main!")
layout.addWidget(self.btnMain)
self.setGeometry(550, 65, 300, 200)
self.setWindowTitle('MainWindow')
self.btn.clicked.connect(self.on_btn)
self.btnMain.clicked.connect(self.on_btnMain)
self.msg = MsgBox()
self.thread = None
self.threadMain = None
def on_btn(self):
''' Starting or Stopping an Additional Stream-WorkThread from the main window '''
# Input parameters for transfer to the stream, if not specified, we pass default `0`
startParm = int(self.lineEdit.text()) if self.lineEdit.text()!="" else 0
if self.thread is None:
self.thread = WorkThread(startParm)
self.thread.threadSignal.connect(self.on_threadSignal)
self.thread.start()
self.btn.setText("Stop thread")
self.lineEdit.hide()
else:
self.thread.terminate()
self.thread = None
self.btn.setText("Start thread")
self.lineEdit.show()
def on_threadSignal(self, value):
''' Visualization of streaming data-WorkThread. '''
self.msg.label.setText(str(value))
self.labelThread.setText("The result of the Thread task: " + str(value)) # We show also in the main window
# We restore the rendering of the stream window if it was closed. The flow is working.
if not self.msg.isVisible():
self.msg.show()
def on_btnMain(self):
''' Starting or Stopping the Main Thread-WorkThreadMain '''
cM = random.randrange(1, 100)
if self.threadMain is None:
self.threadMain = WorkThreadMain(cM)
self.threadMain.threadSignalMain.connect(self.on_threadSignalMain)
self.threadMain.start()
self.btnMain.setText("Stop Main")
else:
self.threadMain.terminate()
self.threadMain = None
self.btnMain.setText("Start Main")
def on_threadSignalMain(self, value):
''' Visualization of streaming data WorkThreadMain '''
self.labelMain.setText("The result of the Main task: " + str(value))
if __name__ == '__main__':
app = Qt.QApplication([])
mw = MainWindow()
mw.show()
app.exec()