1

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

3
  • 2
    Try adding QApplication.processEvents() right after enabling. Note that if the process takes a long time, it may still freeze the window (including possibile refresh caused by resizing or other aspects); if the "time-consuming calculation" is completely out of your control and doesn't involve I/O (including network), you should probably consider multiprocessing; otherwise, add other processEvents() at regular intervals/iterations, or consider that, a QThread (or even a QRunnable) might be a better solution for I/O aspects. Commented Nov 19, 2023 at 19:40
  • many GUIs don't update window directly but they wait for end of your code to redraw all changes in one moment - this way it has less work to redraw window and window doesn't blink when it has to redraw it again and again. So it sometimes need to force GUI to redraw it at some moment instead of waiting to the end of function. Commented Nov 19, 2023 at 23:51
  • Does this answer your question? Background thread with QThread in PyQt Commented Nov 20, 2023 at 1:02

1 Answer 1

0

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))
answered Nov 22, 2023 at 5:42
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.