PyQt6 problems with label background color changes
-
So I've followed the tutorial linked here:
https://realpython.com/python-pyqt-qthread/I got the code in the tutorial working.
Excited I decided to create an app where the color of the label changes while the application loads. The purpose of this is to simulate a loading screen.
However, when I tried my own code to create a loading screen the blinker blinks once and it freezes while the worker thread is running. Below you will see me clicking the start button and not only does the color not change until the end (and once to boot), but the GUI freezes as when I move the window it doesn't register until after the task is finished.
I'm not sure what going on.
Below is my full code:
#PyQt from PyQt6.QtGui import* from PyQt6 import QtWidgets from PyQt6.QtCore import QObject, QThread, pyqtSignal from PyQt6.QtWidgets import* #Others import time import sys class Worker (QObject): finished = pyqtSignal() color_change = pyqtSignal(int) def run(self): for i in range(5): time.sleep(1) self.color_change.emit(i + 1) self.finished.emit() class MainWindow(QWidget): def __init__ (self): super().__init__() self.title = "Window" self.left = 200 self.top = 300 self.width = 300 self.height = 300 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top,self.width, self.height) self.label() self.start_button() self.show() def label(self): self.loading_window_label = QLabel(self) self.loading_window_label.setGeometry(40,40,40,40) self.loading_window_label.setStyleSheet('background-color: red') def start_button(self): self.s_button = QtWidgets.QPushButton(self) self.s_button.setText('Start') self.s_button.clicked.connect(self.run_program) def run_program(self): self.loading() time.sleep(2) print("Loading...") time.sleep(2) print("Loading...") def blink(self, number): color_dict = {1:'orange', 2:'yellow', 3:'orange', 4:'yellow', 5:'green'} self.loading_window_label.setStyleSheet(f'background-color: {color_dict[number]}') def loading(self): #Creating thread self.thread = QThread() self.worker = Worker() self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) #Killing the thread self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) #Create the connection to the function self.worker.color_change.connect(self.blink) #Start the thread self.thread.start() #Resets self.s_button.setEnabled(False) self.thread.finished.connect(lambda: self.s_button.setEnabled(True)) #Have color go to red self.thread.finished.connect(lambda:self.loading_window_label.setStyleSheet(f'background-color: red')) if __name__ == '__main__': app = QApplication(sys.argv) ex = MainWindow() code = app.exec() sys.exit(code)
Any help would be great!
-
Figured it out!
Had to have the time.sleep(2) in the run_program(self) function be it's own function and run it as a thread:
Full working code:
#PyQt from PyQt6.QtGui import* from PyQt6 import QtWidgets from PyQt6.QtCore import QObject, QThread, pyqtSignal from PyQt6.QtWidgets import* #Others import threading import time import sys class Worker (QObject): finished = pyqtSignal() color_change = pyqtSignal(int) def run(self): for i in range(5): time.sleep(1) self.color_change.emit(i + 1) self.finished.emit() class MainWindow(QWidget): def __init__ (self): super().__init__() self.title = "Window" self.left = 200 self.top = 300 self.width = 300 self.height = 300 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top,self.width, self.height) self.label() self.start_button() self.show() def label(self): self.loading_window_label = QLabel(self) self.loading_window_label.setGeometry(40,40,40,40) self.loading_window_label.setStyleSheet('background-color: red') def start_button(self): self.s_button = QtWidgets.QPushButton(self) self.s_button.setText('Start') self.s_button.clicked.connect(self.run_program) def run_program(self): waiting_thread = threading.Thread(target=MainWindow.waiting) waiting_thread.daemon = True waiting_thread.start() self.loading() def waiting(): time.sleep(2) print("Loading...") time.sleep(2) print("Loading...") def blink(self, number): color_dict = {1:'orange', 2:'yellow', 3:'orange', 4:'yellow', 5:'green'} self.loading_window_label.setStyleSheet(f'background-color: {color_dict[number]}') def loading(self): #Creating thread self.thread = QThread() self.worker = Worker() self.worker.moveToThread(self.thread) self.thread.started.connect(self.worker.run) #Killing the thread self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) #Create the connection to the function self.worker.color_change.connect(self.blink) #Start the thread self.thread.start() #Resets self.s_button.setEnabled(False) self.thread.finished.connect(lambda: self.s_button.setEnabled(True)) #Have color go to red self.thread.finished.connect(lambda:self.loading_window_label.setStyleSheet(f'background-color: red')) if __name__ == '__main__': app = QApplication(sys.argv) ex = MainWindow() code = app.exec() sys.exit(code)