首页 > 解决方案 > 没有完成的信号

问题描述

永远不会self.onFinished通过self.process.finished.connect()信号达到功能。该过程完成后,我想向对话框提供其他命令。

class UpdateDialog(QtWidgets.QDialog):

    outputSignal = QtCore.pyqtSignal(str)
    errorSignal = QtCore.pyqtSignal(str)

    def __init__(self, parent = None):
        super(UpdateDialog, self).__init__(parent)
        uic.loadUi(os.path.join(os.environ.get("ROOT_PATH"), "testd.ui"), self)

        self.process = QtCore.QProcess()
        self.completed = False
        self.process.readyReadStandardOutput.connect(self.onReadyReadStandardOutput)
        self.process.readyReadStandardError.connect(self.onReadyReadStandardError)

    def onReadyReadStandardOutput(self):
        error = self.process.readAllStandardError().data().decode()
        self.plainTextEdit_st.appendPlainText(error)
        self.errorSignal.emit(error)

    def onReadyReadStandardError(self):
        error = self.process.readAllStandardError().data().decode()
        self.plainTextEdit_st.appendPlainText(error)
        self.errorSignal.emit(error)
    
    def run(self, command):
        self.plainTextEdit_st.clear()
        self.process.finished.connect(self.onFinished)
        self.process.start(command)
    
    def onFinished(self):
        self.completed = True

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    dialog = UpdateDialog()
    dialog.show()
    dialog.errorSignal.connect(lambda error: print(error))
    dialog.outputSignal.connect(lambda output: print(output))
    dialog.run("git clone --progress https://github.com/myrepo/test.git C:\\test\\")
    if dialog.completed:
        print("test")
    sys.exit(app.exec_())

标签: pythonpython-3.xpyqt5

解决方案


Qt 通过信号异步工作,也就是说,启动的任务(例如 run 方法)不会立即执行,而是在 eventloop 执行后的瞬间执行,因此当您评估 dialgo.completed 时,它甚至还没有完成。启动 QProcess。

Qt 使用面向事件的编程范式工作,因此逻辑是实现一个函数,该函数在发生某些事情时执行某些操作,例如,您想在触发完成信号时打印文本,那么该任务必须在关联的插槽中完成信号:

def onFinished(self):
    print("test")

顺序逻辑不能直接在 Qt 中工作,因此您必须更改实现以实现您想要的。

类似的替代方案是:

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = UpdateDialog()
    dialog.show()
    dialog.errorSignal.connect(print)
    dialog.outputSignal.connect(print)
    dialog.run("git clone --progress https://github.com/myrepo/test.git C:\\test\\")

    def handle_finished():
        print("test")

    dialog.process.finished.connec(handle_finished)
    sys.exit(app.exec_())

或者:

class UpdateDialog(QtWidgets.QDialog):

    outputSignal = QtCore.pyqtSignal(str)
    errorSignal = QtCore.pyqtSignal(str)
    finished = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(UpdateDialog, self).__init__(parent)
        uic.loadUi(os.path.join(os.environ.get("ROOT_PATH"), "testd.ui"), self)
        self.process = QtCore.QProcess()
        self.process.readyReadStandardOutput.connect(self.onReadyReadStandardOutput)
        self.process.readyReadStandardError.connect(self.onReadyReadStandardError)
        self.process.finished.connect(self.finished)

    def onReadyReadStandardOutput(self):
        output = self.process.readAllStandardError().data().decode()
        self.plainTextEdit_st.appendPlainText(output)
        self.outputSignal.emit(output)

    def onReadyReadStandardError(self):
        error = self.process.readAllStandardError().data().decode()
        self.plainTextEdit_st.appendPlainText(error)
        self.errorSignal.emit(error)

    def run(self, command):
        self.plainTextEdit_st.clear()
        self.process.start(command)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = UpdateDialog()
    dialog.show()
    dialog.errorSignal.connect(print)
    dialog.outputSignal.connect(print)
    dialog.run("git clone --progress https://github.com/myrepo/test.git C:\\test\\")

    def handle_finished():
        print("test")

    dialog.finished.connec(handle_finished)
    sys.exit(app.exec_())

我建议您阅读Signals & Slots,以便您了解更多关于 Qt 的工作原理


推荐阅读