Qt:QPushButton被子进程阻止

时间:2013-04-04 06:48:35

标签: python qt process pyqt pyside

给出以下代码

button = ...
process = QProcess()
button.clicked.connect(start_process)

def start_process():

    # Disable the button
    button.setEnabled(False)
    # This seems to have no effect (...)

    # This also has no effect, thus commented out.
    # QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

    # Execute the program in a blocking way
    process.execute('/usr/bin/libreoffice')
    # (...) as right now, while libreoffice is running and I click the button
    # no animation is taking place, but the click !! is getting registered !!
    # If I terminate libreoffice, these clicks are executed and this function is
    # called again for every click done.

    # When the process and all its children have terminated, enable the button again
    button.setEnabled(True)

我已经在代码中解释了我的问题。我认为它与主线程(gui线程)被process.execute(...)调用阻止,同时setEnabled(False)调用仍然在队列中等等。

我想要实现的目标:

  1. 用户点击按钮 - >按钮被禁用并启动了LibreOffice
  2. 当LibreOffice正在运行时,我的GUI被阻止,点击该按钮未被注册
  3. 用户退出LibreOffice,我的GUI被取消阻止,再次启用Button以进行另一次LibreOffice启动
  4. 最终可能起作用的是什么:

    我没有使用process.execute(...),而是使用process.start(...)并将start()信号挂钩到我自己的函数以禁用按钮和finished()信号以再次启用该按钮?

    到底是什么工作:

    class C(QObject):
        """
        Host (Communicator) for all my signals
        """
        enableButton = QtCore.Signal()
        disableButton = QtCore.Signal()
    
    
    class MainWindow(QtGui.QMainWindow):
        def __init__(self, program=None, c=None, parent=None):
            super(MainWindow, self).__init__(parent)
            self.ui = Ui_mainWindow()
            self.ui.setupUi(self)
    
            self.program = program
            self.c = c  # Reference to the C instance
            self.setupSignals()
    
        def setupSignals(self):
            self.ui.btnStart.clicked.connect(self.program.start) # Trigger button
    
            # Register for events from UI Thread
            self.c.enableButton.connect(self.button_enable)
            self.c.disableButton.connect(self.button_disable)
    
        def button_enable(self):
            self.ui.btnStart.setEnabled(True)
    
        def button_disable(self):
            self.ui.btnStart.setEnabled(False)
    
    
    class Program(object):
        def __init__(self, c=None):
            self.c = c
            self.proc = QProcess()  # The process to run in the start method.
                                    # needed here because its runs out of scope otherwise.
    
        def start(self):
    
            def _onStart():
                self.c.disableButton.emit()
                print("on Start")
    
            def _onFinish():
                self.c.enableButton.emit()
                print("on Finish")
    
            def _onError():
                print("on Error")
    
            self.proc.started.connect(_onStart)
            self.proc.finished.connect(_onFinish)
            self.proc.error.connect(_onError)
            self.proc.start('/usr/bin/libreoffice')  # Waits until process ends
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        c = C()
    
        program = Program(c=c)
        main_window = MainWindow(program=program, c=c)
        main_window.show()
    
        sys.exit(app.exec_())
    

    我希望我没有过多地剥夺它。如果您有任何疑问,请继续。

1 个答案:

答案 0 :(得分:5)

你已经自己回答了你的问题:),所以我只是总结一下:

  • QProcess.execute(它是静态的,顺便说一句,所以在这种情况下不需要创建QProcess对象)启动子进程并为子进程等待完成的过程 - 当子进程正在运行时,调用进程被阻止,您的UI被冻结

  • 要实现您的需求,请使用QProcess.start()异步启动子进程,并连接相应的信号started()finished()。有关要考虑的一些细节,请参阅文档中的说明。