Issue
I want to open another window upon a successful login but it continuously give this error.
QCoreApplication::exec: The event loop is already running
Here is the code. LoginWindow - Login Page
MainWindow - Post login page
Is there anyway I can open another window upon a successful login and close the current one.
from PyQt5.QtWidgets import QMainWindow, QApplication
from login_ui import *
import sys
LOGGED_IN = False
TOKEN = ""
class LoginWindow(QMainWindow, Ui_LoginWindow):
GLOBAL_STATE = True
loginPortal = QApplication([])
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowFlag(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.show()
self.handleButtons()
sys.exit(self.loginPortal.exec_())
def handleButtons(self):
self.CloseBtn.clicked.connect(self.close)
self.MinBtn.clicked.connect(self.showMinimized)
self.loginBtn.clicked.connect(self.login)
def login(self):
if self.username.text() == "admin" and self.password.text() == "password":
LOGGED_IN = True
TOKEN = "admin"
elif self.username.text() == "coord" and self.password.text() == "password":
LOGGED_IN = True
TOKEN = "coord"
else:
LOGGED_IN = False
Token = None
if LOGGED_IN:
MainWindow().show()
else:
self.close()
self.loginPortal.quit()
from main_ui import *
class MainWindow(QMainWindow, Ui_MainWindow):
app = QApplication([])
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowFlag(Qt.FramelessWindowHint)
self.showMaximized()
self.handleButtons()
sys.exit(self.app.exec_())
def handleButtons(self):
self.MinBtn.clicked.connect(self.showMinimized)
self.MaxBtn.clicked.connect(self.maximize)
self.CloseBtn.clicked.connect(self.close)
def maximize(self):
if self.GLOBAL_STATE:
self.showNormal()
self.GLOBAL_STATE = False
else:
self.showMaximized()
self.GLOBAL_STATE = True
if __name__ == "__main__":
LoginWindow()
Solution
There are two problems with your code:
- Only one QApplication instance should exist.
- You're creating a QApplication in the class definition.
The second problem is important, as QtWidgets can only be created when a QApplication is created. When python opens a script, it also initializes all the classes in its main indentation, which also means that every function in the base indentation of the class is executed.
In your case, it means that when each class is loaded, each one will try to create a QApplication, since app = QApplication([])
is in their main indentation. As explained in the first point, only one QApplication instance can only exist.
While technically your code could run fine when using a single class (the QApplication is created before actually creating the widget instance), this leads to problems exactly like in your case.
A possible workaround would be to check if a QApplication already exists:
# note: this is just for explanation purposes, do NOT do this unless you
# really know what you're doing
class LoginWindow(QMainWindow, Ui_MainWindow):
if not QApplication.instance():
loginPortal = QApplication([])
# ...
class MainWindow(QMainWindow, Ui_MainWindow):
if not QApplication.instance():
app = QApplication([])
But that's not a good approach anyway, and the reason is that the application should be also executed with exec_()
(or exec()
). While you're doing it within the __init__
of each widget, that's absolutely not the place for that: exec_()
is blocking, which prevents returning the actual instance to the caller until the application quits. Even if you're not actually interested in that, it's not good practice, as the __init__
should always return as soon as possible. Finally, when you try to create the main window instance, it will try to exec the other QApplication instance, and this is the (final) source of your problem.
That's what the common if __name__ == '__main__':
is important for: ensuring that only the main program executes what should be actually run, and in case of Qt, to create and run the only QApplication that should ever exist in the program lifetime.
A better approach when dealing with multiple windows is to create a signal and use that to interact with anything else.
This is a possible correct version of your code (be aware of the commented lines)
class LoginWindow(QMainWindow, Ui_LoginWindow):
loggedSignal = pyqtSignal()
GLOBAL_STATE = True
# loginPortal = QApplication([])
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowFlag(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.show()
self.handleButtons()
# sys.exit(self.loginPortal.exec_())
# ...
def login(self):
# ...
if LOGGED_IN:
self.loggedSignal.emit()
else:
QApplication.quit()
self.close()
class MainWindow(QMainWindow, Ui_MainWindow):
# app = QApplication([])
def __init__(self):
super().__init__()
self.setupUi(self)
self.setWindowFlag(Qt.FramelessWindowHint)
# self.showMaximized()
self.handleButtons()
# sys.exit(self.app.exec_())
if __name__ == '__main__':
app = QApplication(sys.argv)
login = LoginWindow()
mainWindow = MainWindow()
login.loggedSignal.connect(mainWindow.showMaximized)
sys.exit(app.exec_())
Note that you are using the GLOBAL_STATE
in the main window, but you defined it in the login window only instead.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.