简体   繁体   English

登录成功后打开另一个window PyQt5 Python3

[英]Opening another window after successful login PyQt5 Python3

I want to open another window upon a successful login but it continuously give this error.我想在成功登录后打开另一个 window 但它不断给出这个错误。

QCoreApplication::exec: The event loop is already running QCoreApplication::exec: 事件循环已经在运行

Here is the code.这是代码。 LoginWindow - Login Page LoginWindow - 登录页面

MainWindow - Post login page MainWindow - 登录后页面

Is there anyway I can open another window upon a successful login and close the current one.无论如何我可以在成功登录后打开另一个 window 并关闭当前一个。

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()

There are two problems with your code:您的代码有两个问题:

  1. Only one QApplication instance should exist.应该只存在一个 QApplication 实例。
  2. You're creating a QApplication in the class definition.您正在 class 定义中创建 QApplication。

The second problem is important, as QtWidgets can only be created when a QApplication is created.第二个问题很重要,因为只有在创建 QApplication 时才能创建 QtWidget。 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.当 python 打开一个脚本时,它也会初始化其主缩进中的所有类,这也意味着 class 的基本缩进中的每个 function 都被执行。

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.在您的情况下,这意味着当每个 class 加载时,每个人都会尝试创建一个 QApplication,因为app = QApplication([])在它们的主缩进中。 As explained in the first point, only one QApplication instance can only exist.正如第一点所解释的,只能存在一个 QApplication 实例。

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.虽然从技术上讲,当使用单个 class (在实际创建小部件实例之前创建 QApplication)时,您的代码可以正常运行,但这会导致与您的情况完全相同的问题。

A possible workaround would be to check if a QApplication already exists:一种可能的解决方法是检查 QApplication 是否已经存在:

# 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() ).但这无论如何都不是一个好方法,原因是应用程序也应该使用exec_() (或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.当您在每个小部件的__init__中执行此操作时,绝对不是这样做的地方: exec_()是阻塞的,这会阻止将实际实例返回给调用者,直到应用程序退出。 Even if you're not actually interested in that, it's not good practice, as the __init__ should always return as soon as possible.即使您实际上对此并不感兴趣,这也不是一个好习惯,因为__init__应该总是尽快返回。 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.最后,当您尝试创建主 window 实例时,它将尝试执行另一个QApplication 实例,这是您问题的(最终)来源。

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.这就是常见的if __name__ == '__main__':的重要性:确保只有主程序执行应该实际运行的内容,并且在 Qt 的情况下,创建和运行应该存在于程序生命周期中的唯一QApplication .

A better approach when dealing with multiple windows is to create a signal and use that to interact with anything else.处理多个 windows 时,更好的方法是创建一个信号并使用它与其他任何东西进行交互。

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.请注意,您在主 window 中使用GLOBAL_STATE ,但您仅在登录 window 中定义了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM