Must construct a QApplication before a QWidget
-
hello,
I have created a GUI Windows app. It starts with a splash screen and then transitions to the main window (home screen), allowing users to navigate to other pages by clicking on buttons. The use of the timer to automatically close the splash screen after a certain time. when I ran my below code I got an error message QWidget: Must construct a QApplication before a QWidget .. please help me to solve this.
code 👇import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton from PyQt5.QtCore import QTimer, Qt from PyQt5.QtGui import QPixmap from PyQt5 import uic, QtWidgets, QtGui, QtCore from ui_splash_screen import Ui_SplashScreen # Your existing SplashScreen class class SplashScreen(QMainWindow): # ... (your existing SplashScreen code here) ... def __init__(self): QtWidgets.QMainWindow.__init__(self) self.ui = Ui_SplashScreen() self.ui.setupUi(self) # remove titile bar self.setWindowFlag(QtCore.Qt.FramelessWindowHint) self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # set app logo pixmap = QtGui.QPixmap("logo.png") self.ui.log_img.setPixmap(pixmap) self.ui.log_img.setScaledContents(True) self.ui.log_img.setSizePolicy( QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) # hide background self.ui.background.setMaximumHeight(0) # SET INITIOLS STATUS self.ui.status.setText("Loading..") # Initialize animation self.logo_animation() self.description_animation() self.start_animation() # qtimer self.timer = QtCore.QTimer() self.timer.timeout.connect(self.progress) # time in milisecond self.timer.start(35) # change status QtCore.QTimer.singleShot( 2500, lambda: self.ui.status.setText("Loading Data....")) QtCore.QTimer.singleShot( 4500, lambda: self.ui.status.setText("Loading App....")) QtCore.QTimer.singleShot( 6500, lambda: self.ui.status.setText("Starting App....")) # animate app logo def logo_animation(self): opacity_effect = QtWidgets.QGraphicsOpacityEffect(self.ui.log_img) self.ui.log_img.setGraphicsEffect(opacity_effect) self.logo_opacity_animation = QtCore.QPropertyAnimation( opacity_effect, b'opacity', duration=1500, startValue=0, endValue=1 ) self.logo_opacity_animation.setEasingCurve( QtCore.QEasingCurve.InOutCubic) self.logo_opacity_animation.start() # animate app description # //////////////////////////////// def description_animation(self): opacity_effect = QtWidgets.QGraphicsOpacityEffect(self.ui.background) self.ui.background.setGraphicsEffect(opacity_effect) geometry_animation = QtCore.QPropertyAnimation( self.ui.background, b'maximumHeight', duration=1000, startValue=0, endValue=228, ) geometry_animation.setEasingCurve(QtCore.QEasingCurve.InOutCubic) opacity_animation = QtCore.QPropertyAnimation( opacity_effect, b'opacity', duration=500, startValue=0, endValue=1 ) self.description_animation = QtCore.QParallelAnimationGroup( self.ui.background) self.description_animation.addAnimation(geometry_animation) self.description_animation.addAnimation(opacity_animation) # start animation def start_animation(self): self.anim_group = QtCore.QSequentialAnimationGroup(self) self.anim_group.addAnimation(self.logo_opacity_animation) self.anim_group.addAnimation(self.description_animation) self.anim_group.start() # progress function def progress(self): global COUNTER # set value to progressbar self.ui.progressBar.setValue(COUNTER) self.ui.percentage.setText(f"{int(COUNTER)}%") # CLOSE SPLASH SCREEN AND OPEN APP if COUNTER > 100: # STOP TIMER self.timer.stop() # SHOW MAIN WINDOW self.main = MainWindow() self.main.show() # CLOSE SPLASH SCREEN self.close() # Main application window class MainWindow(QMainWindow): def __init__(self): super().__init__() # Load the UI from main_window.ui (your home screen) self.load_ui("main_window.ui") # Connect button clicks to relevant actions self.take_sample_btn.clicked.connect(self.show_take_sample_screen) self.train_model_btn.clicked.connect(self.show_train_model_screen) self.calibrate_btn.clicked.connect(self.show_calibrate_screen) self.get_prediction_btn.clicked.connect(self.show_get_prediction_screen) self.pick_a_model_btn.clicked.connect(self.show_pick_a_model_screen) self.quit_btn.clicked.connect(self.show_close_screen) def load_ui(self, ui_file): # Function to load UI files uic.loadUi(ui_file, self) def show_take_sample_screen(self): # Handle button click to navigate to TakeSampleScreen self.load_ui("take_sample_screen.ui") self.setup_take_sample_screen_ui() # Add more setup code as needed... def show_train_model_screen(self): # Handle button click to navigate to TrainModelScreen self.load_ui("model_training_screen.ui") self.setup_train_model_screen_ui() # Add more setup code as needed... def show_calibrate_screen(self): self.load_ui("calibrate_screen.ui") self.setup_calibrate_screen_ui() # Add similar methods for other screens... def show_get_prediction_screen(self): self.load_ui("prediction_screen.ui") self.setup_get_prediction_ui() def show_pick_a_model_screen(self): self.load_ui("pick_model.ui") self.setup_pick_model_ui() def show_close_screen(self): QtCore.QCoreApplication.quit() def setup_take_sample_screen_ui(self): # Setup UI elements for TakeSampleScreen self.backButton.clicked.connect(self.show_main_window) # Add more setup code as needed... def setup_train_model_screen_ui(self): # Setup UI elements for TrainModelScreen self.backButton.clicked.connect(self.show_main_window) # Add more setup code as needed... def setup_calibrate_screen_ui(self): self.backButton.clicked.connect(self.show_main_window) def setup_get_prediction_ui(self): self.backButton.clicked.connect(self.show_main_window) def setup_pick_model_ui(self): self.backButton.clicked.connect(self.show_main_window) # Add similar setup methods for other screens... def show_main_window(self): # Return to the main window (home screen) self.load_ui("main_window.ui") def main(): # Create the QApplication instance app = QApplication(sys.argv) # Create the SplashScreen object splash_screen = SplashScreen() splash_screen.show() # Create a timer to close the splash screen after a certain time (e.g., 3 seconds) timer = QTimer() timer.timeout.connect(splash_screen.close) timer.start(3000) # 3000 milliseconds (3 seconds) splash_screen.finished.connect(lambda: show_main_window()) sys.exit(app.exec_()) def show_main_window(): global main_window main_window = MainWindow() main_window.show() if __name__ == '__main__': main()
this is the terminal output 👇
-
hello,
I have created a GUI Windows app. It starts with a splash screen and then transitions to the main window (home screen), allowing users to navigate to other pages by clicking on buttons. The use of the timer to automatically close the splash screen after a certain time. when I ran my below code I got an error message QWidget: Must construct a QApplication before a QWidget .. please help me to solve this.
code 👇import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton from PyQt5.QtCore import QTimer, Qt from PyQt5.QtGui import QPixmap from PyQt5 import uic, QtWidgets, QtGui, QtCore from ui_splash_screen import Ui_SplashScreen # Your existing SplashScreen class class SplashScreen(QMainWindow): # ... (your existing SplashScreen code here) ... def __init__(self): QtWidgets.QMainWindow.__init__(self) self.ui = Ui_SplashScreen() self.ui.setupUi(self) # remove titile bar self.setWindowFlag(QtCore.Qt.FramelessWindowHint) self.setAttribute(QtCore.Qt.WA_TranslucentBackground) # set app logo pixmap = QtGui.QPixmap("logo.png") self.ui.log_img.setPixmap(pixmap) self.ui.log_img.setScaledContents(True) self.ui.log_img.setSizePolicy( QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) # hide background self.ui.background.setMaximumHeight(0) # SET INITIOLS STATUS self.ui.status.setText("Loading..") # Initialize animation self.logo_animation() self.description_animation() self.start_animation() # qtimer self.timer = QtCore.QTimer() self.timer.timeout.connect(self.progress) # time in milisecond self.timer.start(35) # change status QtCore.QTimer.singleShot( 2500, lambda: self.ui.status.setText("Loading Data....")) QtCore.QTimer.singleShot( 4500, lambda: self.ui.status.setText("Loading App....")) QtCore.QTimer.singleShot( 6500, lambda: self.ui.status.setText("Starting App....")) # animate app logo def logo_animation(self): opacity_effect = QtWidgets.QGraphicsOpacityEffect(self.ui.log_img) self.ui.log_img.setGraphicsEffect(opacity_effect) self.logo_opacity_animation = QtCore.QPropertyAnimation( opacity_effect, b'opacity', duration=1500, startValue=0, endValue=1 ) self.logo_opacity_animation.setEasingCurve( QtCore.QEasingCurve.InOutCubic) self.logo_opacity_animation.start() # animate app description # //////////////////////////////// def description_animation(self): opacity_effect = QtWidgets.QGraphicsOpacityEffect(self.ui.background) self.ui.background.setGraphicsEffect(opacity_effect) geometry_animation = QtCore.QPropertyAnimation( self.ui.background, b'maximumHeight', duration=1000, startValue=0, endValue=228, ) geometry_animation.setEasingCurve(QtCore.QEasingCurve.InOutCubic) opacity_animation = QtCore.QPropertyAnimation( opacity_effect, b'opacity', duration=500, startValue=0, endValue=1 ) self.description_animation = QtCore.QParallelAnimationGroup( self.ui.background) self.description_animation.addAnimation(geometry_animation) self.description_animation.addAnimation(opacity_animation) # start animation def start_animation(self): self.anim_group = QtCore.QSequentialAnimationGroup(self) self.anim_group.addAnimation(self.logo_opacity_animation) self.anim_group.addAnimation(self.description_animation) self.anim_group.start() # progress function def progress(self): global COUNTER # set value to progressbar self.ui.progressBar.setValue(COUNTER) self.ui.percentage.setText(f"{int(COUNTER)}%") # CLOSE SPLASH SCREEN AND OPEN APP if COUNTER > 100: # STOP TIMER self.timer.stop() # SHOW MAIN WINDOW self.main = MainWindow() self.main.show() # CLOSE SPLASH SCREEN self.close() # Main application window class MainWindow(QMainWindow): def __init__(self): super().__init__() # Load the UI from main_window.ui (your home screen) self.load_ui("main_window.ui") # Connect button clicks to relevant actions self.take_sample_btn.clicked.connect(self.show_take_sample_screen) self.train_model_btn.clicked.connect(self.show_train_model_screen) self.calibrate_btn.clicked.connect(self.show_calibrate_screen) self.get_prediction_btn.clicked.connect(self.show_get_prediction_screen) self.pick_a_model_btn.clicked.connect(self.show_pick_a_model_screen) self.quit_btn.clicked.connect(self.show_close_screen) def load_ui(self, ui_file): # Function to load UI files uic.loadUi(ui_file, self) def show_take_sample_screen(self): # Handle button click to navigate to TakeSampleScreen self.load_ui("take_sample_screen.ui") self.setup_take_sample_screen_ui() # Add more setup code as needed... def show_train_model_screen(self): # Handle button click to navigate to TrainModelScreen self.load_ui("model_training_screen.ui") self.setup_train_model_screen_ui() # Add more setup code as needed... def show_calibrate_screen(self): self.load_ui("calibrate_screen.ui") self.setup_calibrate_screen_ui() # Add similar methods for other screens... def show_get_prediction_screen(self): self.load_ui("prediction_screen.ui") self.setup_get_prediction_ui() def show_pick_a_model_screen(self): self.load_ui("pick_model.ui") self.setup_pick_model_ui() def show_close_screen(self): QtCore.QCoreApplication.quit() def setup_take_sample_screen_ui(self): # Setup UI elements for TakeSampleScreen self.backButton.clicked.connect(self.show_main_window) # Add more setup code as needed... def setup_train_model_screen_ui(self): # Setup UI elements for TrainModelScreen self.backButton.clicked.connect(self.show_main_window) # Add more setup code as needed... def setup_calibrate_screen_ui(self): self.backButton.clicked.connect(self.show_main_window) def setup_get_prediction_ui(self): self.backButton.clicked.connect(self.show_main_window) def setup_pick_model_ui(self): self.backButton.clicked.connect(self.show_main_window) # Add similar setup methods for other screens... def show_main_window(self): # Return to the main window (home screen) self.load_ui("main_window.ui") def main(): # Create the QApplication instance app = QApplication(sys.argv) # Create the SplashScreen object splash_screen = SplashScreen() splash_screen.show() # Create a timer to close the splash screen after a certain time (e.g., 3 seconds) timer = QTimer() timer.timeout.connect(splash_screen.close) timer.start(3000) # 3000 milliseconds (3 seconds) splash_screen.finished.connect(lambda: show_main_window()) sys.exit(app.exec_()) def show_main_window(): global main_window main_window = MainWindow() main_window.show() if __name__ == '__main__': main()
this is the terminal output 👇
@Thiyo
Hello and welcome.It would be helpful if you used the Code tags (
</>
icon) around any code blocks, especially if you use python where lead spacing is vital. If you did this it might be easier to spot where aQWidget
is created before aQApplication
, e.g. perhaps in a global variable you have? -
Hi @Thiyo,
QMainWindow
inheritsQWidget
, so this line is creating aQWidget
globally:global main_window
Which, of course, is happening before your
main
creates theQApplication
, thus the error message you see.As per the docs, you need to create your
main_window
after you create theQMainApplication
- most likely by makingmain_window
non-global, but I'll leave the exact details to you and others that know Python better than I do :)Cheers.
-
Hi @Thiyo,
QMainWindow
inheritsQWidget
, so this line is creating aQWidget
globally:global main_window
Which, of course, is happening before your
main
creates theQApplication
, thus the error message you see.As per the docs, you need to create your
main_window
after you create theQMainApplication
- most likely by makingmain_window
non-global, but I'll leave the exact details to you and others that know Python better than I do :)Cheers.
@Paul-Colby said in Must construct a QApplication before a QWidget:
global main_window
I'm sure you're right. But I thought
global
in Python gave the variable global scope but did not actually create it until the statement is first hit, which is insidedef show_main_window():
and therefore not until that function is first called, which is not until aftermain()
is called andapp = QApplication(sys.argv)
has been executed? Pythonglobal
is confusing....!P.S.
My advice to @Thiyo is don't useglobal
at all in Python/Qt, C++ manages without needing to do so here! -
@Paul-Colby said in Must construct a QApplication before a QWidget:
global main_window
I'm sure you're right. But I thought
global
in Python gave the variable global scope but did not actually create it until the statement is first hit, which is insidedef show_main_window():
and therefore not until that function is first called, which is not until aftermain()
is called andapp = QApplication(sys.argv)
has been executed? Pythonglobal
is confusing....!P.S.
My advice to @Thiyo is don't useglobal
at all in Python/Qt, C++ manages without needing to do so here!@JonB said in Must construct a QApplication before a QWidget:
@Paul-Colby said in Must construct a QApplication before a QWidget:
global main_window
I'm sure you're right. But I thought
global
in Python gave the variable global scope but did not actually create itThat is correct.
global x
doesn't create an object. It tells the interpreter that future references within the scope in question refer to a global rather than local variable. There's no type information, so the interpreter can't create an object at that point.until the statement is first hit, which is inside
def show_main_window():
We can't tell without the indentation. The code could be:
def show_main_window(): global main_window main_window = MainWindow() # Interpreted as part of the module, not a function.
-
@JonB said in Must construct a QApplication before a QWidget:
@Paul-Colby said in Must construct a QApplication before a QWidget:
global main_window
I'm sure you're right. But I thought
global
in Python gave the variable global scope but did not actually create itThat is correct.
global x
doesn't create an object. It tells the interpreter that future references within the scope in question refer to a global rather than local variable. There's no type information, so the interpreter can't create an object at that point.until the statement is first hit, which is inside
def show_main_window():
We can't tell without the indentation. The code could be:
def show_main_window(): global main_window main_window = MainWindow() # Interpreted as part of the module, not a function.