PyQt changing the widget state while pressing the button

59 views Asked by At

I want a Qlabel to appear when the button is pressed, which informs about the work process.But setenabled(True) is called after start_calc is executed.How to fix it?

from PyQt5 import QtWidgets

import time

class MyWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.mainWidgets = QtWidgets.QWidget()
        self.layout = QtWidgets.QHBoxLayout()

        self.label = QtWidgets.QLabel()
        self.label.setText('loading...')

        self.button = QtWidgets.QPushButton()
        self.button.setText('start')

        self.layout.addWidget(self.button)
        self.layout.addWidget(self.label)

        self.mainWidgets.setLayout(self.layout)
        self.setCentralWidget(self.mainWidgets)

        self.label.setEnabled(False)
        self.button.clicked.connect(self.start_calc)

    def start_calc(self):
        self.label.setEnabled(True)
        time.sleep(3) #Simulating some time-consuming calculation
        self.label.setEnabled(False)

app = QtWidgets.QApplication([])
application = MyWindow()
application.show()
app.exec()

I expected that after pressing the button a message would appear and after time.sleep(3) it will disappear

1

There are 1 answers

0
Sen ZmaKi On

In Qt the main thread is responsible for managing the GUI and making updates to it hence it should never be blocked.

When you press the button, the main thread stops managing the GUI then starts executing the code in the slot and only once it finishes executing does it make the GUI changes. So it sees that you want to enable the label then it sleeps for 3 seconds cause of the time.sleep(3) causing the app to lag for 3 seconds cause remember no GUI management is happening, then it sees again that you want to disable the label, but since it was already disabled ultimately it makes no GUI changes.

If you want to do work in the background and make GUI changes once you're done, create a slot that'll perform the GUI changes on the main thread and connect the slot to a signal. Start a QThread that performs the work required to generate the data required for changes, once it's done have the signal emit to the slot with data needed for the changes.

But in your case a QTimer will suffice since no new data/processing is required to make a change to the GUI.

from PyQt5.QtCore import QTimer

# Your other stuff

    def start_calc(self):
        self.label.setEnabled(True)
        QTimer.singleShot(3000, lambda: self.label.setEnabled(False))