给出以下代码
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)
调用仍然在队列中等等。
我没有使用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_())
我希望我没有过多地剥夺它。如果您有任何疑问,请继续。
答案 0 :(得分:5)
你已经自己回答了你的问题:),所以我只是总结一下:
QProcess.execute
(它是静态的,顺便说一句,所以在这种情况下不需要创建QProcess
对象)启动子进程并为子进程等待完成的过程 - 当子进程正在运行时,调用进程被阻止,您的UI被冻结
要实现您的需求,请使用QProcess.start()
异步启动子进程,并连接相应的信号started()
和finished()
。有关要考虑的一些细节,请参阅文档中的说明。