How to communicate or switch between two windows in PyQt?

后端 未结 5 1501
孤独总比滥情好
孤独总比滥情好 2020-12-17 06:38

I am developing an application using python and Qt.

I have designed 2 Main windows ie..QMainWindow (Not QWidget or QDialog) using Qt.

Let it be.

1.

相关标签:
5条回答
  • 2020-12-17 07:02

    I do agree most of the points jdi raised, but I prefer a slightly different approach.

    • LoginWindow should be a QDialog started as MODAL.
    • Check the return of exec_() (i.e. accept/reject) for login or cancel/quit.
    • Check the login inside the LoginWindow
    • If successful login, launch MainWindow with parameters supplied

    I started coding a simple example before seeing jdi's answer. I might as well put it here.

    import sys
    from PyQt4 import QtGui, QtCore
    
    class LoginDialog(QtGui.QDialog):
        def __init__(self, parent=None):
            super(LoginDialog, self).__init__(parent)
    
            self.username = QtGui.QLineEdit()
            self.password = QtGui.QLineEdit()
            loginLayout = QtGui.QFormLayout()
            loginLayout.addRow("Username", self.username)
            loginLayout.addRow("Password", self.password)
    
            self.buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
            self.buttons.accepted.connect(self.check)
            self.buttons.rejected.connect(self.reject)
    
            layout = QtGui.QVBoxLayout()
            layout.addLayout(loginLayout)
            layout.addWidget(self.buttons)
            self.setLayout(layout)
    
        def check(self):
            if str(self.password.text()) == "12345": # do actual login check
                self.accept()
            else:
                pass # or inform the user about bad username/password
    
    
    class MainWindow(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.label = QtGui.QLabel()
            self.setCentralWidget(self.label)
    
        def setUsername(self, username):
            # do whatever you want with the username
            self.username = username
            self.label.setText("Username entered: %s" % self.username)
    
    
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
    
        login = LoginDialog()
        if not login.exec_(): # 'reject': user pressed 'Cancel', so quit
            sys.exit(-1)      
    
        # 'accept': continue
        main = MainWindow()
        main.setUsername(login.username.text()) # get the username, and supply it to main window
        main.show()
    
        sys.exit(app.exec_())
    
    0 讨论(0)
  • 2020-12-17 07:06

    This is PyQt5 updated version of Avaris. Some exception handling was added to show how to catch a few errors (while coding your thing. Enjoy!

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    # Ref to this OP question. https://stackoverflow.com/questions/9689053/how-to-communicate-or-switch-between-two-windows-in-pyqt4
    
    import sys
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QApplication, QDialog, QDialogButtonBox, QFormLayout, QLabel, QLineEdit, QWidget, QVBoxLayout
    
    class LoginDialog(QtWidgets.QDialog):
        def __init__(self, parent=None):
            super(LoginDialog, self).__init__(parent)
    
            self.username = QLineEdit()
            self.password = QLineEdit()
            loginLayout = QFormLayout()
            loginLayout.addRow("Username", self.username)
            loginLayout.addRow("Password", self.password)
    
            self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            self.buttons.accepted.connect(self.check)
            self.buttons.rejected.connect(self.reject)
    
            layout = QVBoxLayout()
            layout.addLayout(loginLayout)
            layout.addWidget(self.buttons)
            self.setLayout(layout)
    
        def check(self):
            if str(self.password.text()) == "12345": # do actual login check
                self.accept()
            else:
                pass # or inform the user about bad username/password
    
        def my_exception_hook(exctype, value, traceback):
            # Print the error and traceback
            print(exctype, value, traceback)
            # Call the normal Exception hook after
            sys._excepthook(exctype, value, traceback)
            sys.exit(1)
    
        # Back up the reference to the exceptionhook
        sys._excepthook = sys.excepthook
    
        # Set the exception hook to our wrapping function
        sys.excepthook = my_exception_hook
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.label = QLabel()
            self.setCentralWidget(self.label)
    
        def setUsername(self, username):
            # do whatever you want with the username
            self.username = username
            self.label.setText("Username entered: %s" % self.username)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        login = LoginDialog()
        if not login.exec_(): # 'reject': user pressed 'Cancel', so quit
            sys.exit(-1)      # instead of -1 another action can be triggered here.     
    
        # 'accept': continue
        main = MainWindow()
    
        # get the username, and supply it to main window
        main.setUsername(login.username.text())
        main.show()
    
        sys.exit(app.exec_())
    
    0 讨论(0)
  • 2020-12-17 07:06

    to match username and password.

    import sys
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import QApplication, QDialog, QDialogButtonBox, QFormLayout, QLabel, QLineEdit, QWidget, QVBoxLayout, QMessageBox
    
    class LoginDialog(QtWidgets.QDialog):
        def __init__(self, parent=None):
            super(LoginDialog, self).__init__(parent)
    
            self.username = QLineEdit()
            self.password = QLineEdit()
            loginLayout = QFormLayout()
            loginLayout.addRow("Username", self.username)
            loginLayout.addRow("Password", self.password)
    
            self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            self.buttons.accepted.connect(self.check)
            self.buttons.rejected.connect(self.reject)
    
            layout = QVBoxLayout()
            layout.addLayout(loginLayout)
            layout.addWidget(self.buttons)
            self.setLayout(layout)
    
        def check(self):
            if str(self.username.text()) == "foo" and str(self.password.text()) == "bar": # do actual login check
                self.accept()
            else:
                QMessageBox.warning(
                    self, 'Error', 'Bad user or password')
                pass # or inform the user about bad username/password
    
        def my_exception_hook(exctype, value, traceback):
            # Print the error and traceback
            print(exctype, value, traceback)
            # Call the normal Exception hook after
            sys._excepthook(exctype, value, traceback)
            sys.exit(1)
    
        # Back up the reference to the exceptionhook
        sys._excepthook = sys.excepthook
    
        # Set the exception hook to our wrapping function
        sys.excepthook = my_exception_hook
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.label = QLabel()
            self.setCentralWidget(self.label)
    
        def setUsername(self, username):
            # do whatever you want with the username
            self.username = username
            self.label.setText("%s%s%s" % ("Username entered: ", self.username, "\npassword ok!"))
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        login = LoginDialog()
        if not login.exec_(): # 'reject': user pressed 'Cancel', so quit
            sys.exit(-1)      # instead of -1 another action can be triggered here.     
    
        # 'accept': continue
        main = MainWindow()
    
        # get the username, and supply it to main window
        main.setUsername(login.username.text())
        main.show()
    
        sys.exit(app.exec_())
    
    0 讨论(0)
  • 2020-12-17 07:10

    Regardless of your description, I think your LoginWindow should be a QDialog, and your StuffWIndow be the MainWindow, and function like this...

    1. Your StuffWindow MainWindow should be created (not shown)
    2. Call a login() method that creates and exec_() your login QDialog as a application MODAL dialog
    3. Start the app.exec_() event loop now, and wait for the user to interact with login
    4. User interacts with login dialog, and the result of the dialog closing will then allow your app to check its values and choose to show its main interface.

    Here is a quick outline:

    class MainWindow():
    
        def login():
            loginDialog = LoginDialog()
    
            # this is modal. wait for it to close
            if loginDialog.exec_():
                # dialog was accepted. check its values and maybe:
                self.show()
    
            else:
                # maybe reshow the login dialog if they rejected it?
                loginDialog.exec_()
    
    
    if __name__ == "__main__":
    
        app = QApp
        win = MainWindow()
        win.login()
        app.exec_()
    
    0 讨论(0)
  • 2020-12-17 07:18

    Although this is not directly relevant to your question, you should always set QLineEdit.EchoMode for the password field as follows (see here):

    self.password.setEchoMode(QtGui.QLineEdit.Password)
    
    0 讨论(0)
提交回复
热议问题