如何在不关闭 GUI 窗口的情况下停止运行 PyQt5 程序?

Posted

技术标签:

【中文标题】如何在不关闭 GUI 窗口的情况下停止运行 PyQt5 程序?【英文标题】:How to stop running PyQt5 program without closing the GUI window? 【发布时间】:2017-09-25 21:12:40 【问题描述】:

以下代码 ping 一个网站并在 QTextEdit 中打印结果。一键“运行”用于启动 ping。我想要另一个按钮“结束”,它可以在 ping 进程运行时停止它而不关闭 GUI。但目前,“结束”按钮关闭了整个 GUI 窗口。您对如何停止 ping 但保留 GUI 有任何想法,以便我可以通过按“运行”按钮再次启动 ping。

import sys
from PyQt5 import QtCore,QtWidgets

class gui(QtWidgets.QMainWindow):
    def __init__(self):
        super(gui, self).__init__()
        self.initUI()

    def dataReady(self):
        cursor = self.output.textCursor()
        cursor.movePosition(cursor.End)
        cursor.insertText(str(self.process.readAll()))
        self.output.ensureCursorVisible()

    def callProgram(self):
        # run the process
        # `start` takes the exec and a list of arguments
        self.process.start('ping',['127.0.0.1'])

    def initUI(self):
        # Layout are better for placing widgets
        layout = QtWidgets.QHBoxLayout()
        self.runButton = QtWidgets.QPushButton('Run')
        self.runButton.clicked.connect(self.callProgram)
        self.runButton1 = QtWidgets.QPushButton('End')
        self.runButton1.clicked.connect(self.close)

        self.output = QtWidgets.QTextEdit()

        layout.addWidget(self.output)
        layout.addWidget(self.runButton)
        layout.addWidget(self.runButton1)

        centralWidget = QtWidgets.QWidget()
        centralWidget.setLayout(layout)
        self.setCentralWidget(centralWidget)

        # QProcess object for external app
        self.process = QtCore.QProcess(self)
        # QProcess emits `readyRead` when there is data to be read
        self.process.readyRead.connect(self.dataReady)

        # Just to prevent accidentally running multiple times
        # Disable the button when process starts, and enable it when it finishes
        self.process.started.connect(lambda: self.runButton.setEnabled(False))
        self.process.finished.connect(lambda: self.runButton.setEnabled(True))


#Function Main Start
def main():
    app = QtWidgets.QApplication(sys.argv)
    ui=gui()
    ui.show()
    sys.exit(app.exec_())
#Function Main END

if __name__ == '__main__':
    main() 

【问题讨论】:

【参考方案1】:

您必须将clicked 信号与QProcess kill 插槽连接:

def initUI(self):
    [...]
    self.runButton1 = QtWidgets.QPushButton('End')
    # self.runButton1.clicked.connect(self.close)
    [...]

    # QProcess object for external app
    self.process = QtCore.QProcess(self)
    # QProcess emits `readyRead` when there is data to be read
    self.process.readyRead.connect(self.dataReady)
    self.runButton1.clicked.connect(self.process.kill)
    # Just to prevent accidentally running multiple times
    # Disable the button when process starts, and enable it when it finishes
    self.process.started.connect(lambda: self.runButton.setEnabled(False))
    self.process.finished.connect(lambda: self.runButton.setEnabled(True))

【讨论】:

以上是关于如何在不关闭 GUI 窗口的情况下停止运行 PyQt5 程序?的主要内容,如果未能解决你的问题,请参考以下文章

Visual C++/Cli 中的异步睡眠,如何在不使 GUI 停止的情况下创建一个 X 毫秒来调用函数

如何在不使用 sudo 的情况下从终端窗口关闭 Internet 连接?

在没有窗口/GUI 的情况下运行 Pygame

如何停止运行没有 GUI 窗口的 Python .pyw 脚本?

如何在没有 GUI 的情况下运行 makecert.exe?

如何在不冻结 gui 的情况下运行 QProcess 的同步链?