Reputation: 121
I want to implement a loading screen that will be displayed in front of the main or application gui Main_Window
.
The loading screen Load_Window
should contain a gif image and a progress bar that continuously shows how far the main interface Main_Window
has been initialized.
Once the main gui is fully initialized, then the loading screen should disappear and the main GUI be displayed.
So far I've tried the QThread, QSplashscreen and app.processEvent() approaches, but the loading screen was frozen because the pyqt5 event handler isn't running.
In the code example below I have shown the problem as an example.The code is executable!
The for loop in Main_Window
is meant to represent starting configuration files, thread and initializing GUI etc.
How can I display and update the loading screen while the other GUI is being initialized? How can I prevent this effect?
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QDialog, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QThread
from PyQt5.QtCore import QSize
class Main_Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(640, 480))
self.setWindowTitle("Main Window")
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
title = QLabel("I am the main window", self)
title.setAlignment(QtCore.Qt.AlignCenter)
gridLayout.addWidget(title, 0, 0)
# Running the loading screen in own thread, but the event handler is the same :(
# self.Thread = Thread_Load()
# self.Thread.start()
# Call event handler to process the queue
#app.processEvents()
self.show()
for i in range(0,1000000):
print(i)
class Load_Window(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setGeometry(0,0,500,500)
self.setWindowTitle("Load Window")
title = QLabel("I am the Load window", self)
title.setAlignment(QtCore.Qt.AlignCenter)
title.move(200,200)
self.show()
# class Thread_Load(QThread):
# def __init__(self, parent=None):
# QThread.__init__(self, parent)
# Load_Window()
# def run(self):
# # Call event handler to process the queue
# while True:
# app.processEvents()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
LoadWin = Load_Window()
MainWin = Main_Window()
sys.exit(app.exec_())
Upvotes: 2
Views: 5214
Reputation: 158
The answer is the comment left by @musicamante.
If you just wanted to unfreeze your LoadWin, all you need is to put processEvents() right after LoadWin
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
LoadWin = Load_Window()
app.processEvents()
MainWin = Main_Window()
LoadWin.close()
sys.exit(app.exec_())
If you want to the loading screen to move while you trying to load your Main Window, you can send a pyqtSignal to the QDialog to indicate the milestone is achieved.
import sys, time
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QDialog, QLabel, QGridLayout, QWidget, QProgressBar
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtCore import QSize
class Main_Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
Progress = 10
LoadWin.progressUpdate(Progress)
time.sleep(2)
self.setMinimumSize(QSize(640, 480))
self.setWindowTitle("Main Window")
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
Progress = 30
LoadWin.progressUpdate(Progress)
time.sleep(2)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
Progress = 50
LoadWin.progressUpdate(Progress)
time.sleep(2)
title = QLabel("I am the main window", self)
title.setAlignment(QtCore.Qt.AlignCenter)
gridLayout.addWidget(title, 0, 0)
# Running the loading screen in own thread, but the event handler is the same :(
# self.Thread = Thread_Load()
# self.Thread.start()
# Call event handler to process the queue
#app.processEvents()
Progress = 100
LoadWin.progressUpdate(Progress)
self.show()
LoadWin.close()
class Load_Window(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setGeometry(0,0,500,500)
self.setWindowTitle("Load Window")
title = QLabel("I am the Load window", self)
self.pbar = QProgressBar(self)
self.pbar.setGeometry(30, 40, 200, 25)
title.setAlignment(QtCore.Qt.AlignCenter)
title.move(200,200)
self.show()
def progressUpdate(self, progress):
self.pbar.setValue(progress)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
LoadWin = Load_Window()
app.processEvents()
MainWin=Main_Window()
sys.exit(app.exec_())
Upvotes: 1
Reputation: 108
Create a worker function run()
to do all your works and change the values of two global flags as you go. I'm more comfortable with threading
module. But you can find a similar implementation with QThread
too.
import sys, time
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QDialog, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QThread
from PyQt5.QtCore import QSize
alive, Progress = True, 0
class Main_Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(640, 480))
self.setWindowTitle("Main Window")
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
title = QLabel("I am the main window", self)
title.setAlignment(QtCore.Qt.AlignCenter)
gridLayout.addWidget(title, 0, 0)
# Running the loading screen in own thread, but the event handler is the same :(
# self.Thread = Thread_Load()
# self.Thread.start()
# Call event handler to process the queue
#app.processEvents()
self.show()
#for i in range(0,1000000):
# print(i)
class Load_Window(QDialog):
def __init__(self):
QDialog.__init__(self)
self.setGeometry(0,0,500,500)
self.setWindowTitle("Load Window")
title = QLabel("I am the Load window", self)
title.setAlignment(QtCore.Qt.AlignCenter)
title.move(200,200)
self.show()
def run():
global open, Progress
time.sleep(3)
#Do your stuff here, like change the value of Progress as you go through your for loop
alive=False;
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
LoadWin = Load_Window()
import threading
thread1 = threading.Thread(target = run)
thread1.start()
while alive:
time.sleep(.05)
#Set progressbar value as the value of Progress.
app.processEvents()
LoadWin.close()
MainWin=Main_Window()
sys.exit(app.exec_())
Upvotes: 1