Given the following code
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)
I have explained what my problem is in the code. I think it has something to do with the main thread (gui thread) getting blocked by the process.execute(...)
call while having the setEnabled(False)
call still in a queue or something.
What I want to achieve:
- User clicks Button -> Button gets disabled and LibreOffice is launched
- While LibreOffice is running, my GUI is blocked and clicks on the button are not registered
- User exits LibreOffice, my GUI is unblocked and the Button is enabled again for another start of LibreOffice
What might eventually work:
Instead of using process.execute(...)
, I use process.start(...)
and hook the start()
signal to my own function to disable the button and the finished()
signal to enable the button again?
What in the end worked:
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_())
I hope I haven't stripped it too much. If you have questions, go ahead.