PyQt5以实时输出启动外部进程

时间:2018-05-19 15:28:36

标签: python pyqt5

我做了很多研究,但我没有找到一个好的解决方案。 我想创建一个具有小区域的Gui,我可以在其中启动外部程序并在文本区域中实时显示其输出。该程序是控制台应用程序。另外,我必须有可能在任何时候停止它(开始/停止/重新开始)。

1 个答案:

答案 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()              

enter image description here