【问题标题】:How to communicate or switch between two windows in PyQt?如何在 PyQt 中的两个窗口之间进行通信或切换?
【发布时间】:2012-03-30 03:36:18
【问题描述】:

我正在使用 python 和 Qt 开发一个应用程序。

我使用 Qt 设计了 ​​2 个主窗口,即..QMainWindow(不是 QWidget 或 QDialog)。

顺其自然。

1.LoginWindow -- LoginUI(Qt)

2.StuffWindow --- StuffUI

  1. 首先我应该显示登录窗口。

  2. 然后我应该将用户名传递给 StaffWindow(管理东西需要用户名)

  3. 应显示员工窗口并关闭登录窗口..

我怎样才能做到这一点..?帮帮我..

【问题讨论】:

    标签: python pyqt pyqt4 pyqt5 signals-slots


    【解决方案1】:

    匹配用户名和密码。

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

    【讨论】:

      【解决方案2】:

      这是Avaris 的PyQt5 更新版本。添加了一些异常处理以显示如何捕获一些错误(在编写代码时。享受吧!

      #!/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_())
      

      【讨论】:

        【解决方案3】:

        虽然这与您的问题没有直接关系,但您应该始终为密码字段设置 QLineEdit.EchoMode,如下所示(请参阅here):

        self.password.setEchoMode(QtGui.QLineEdit.Password)
        

        【讨论】:

        • 在“我忘记设置这个值”列表中确实有点离题,但 100% 切题。
        【解决方案4】:

        我同意jdi 提出的大部分观点,但我更喜欢稍微不同的方法。

        • LoginWindow 应该是以 MODAL 开头的 QDialog
        • 检查exec_()(即accept/reject)的返回以进行登录或取消/退出。
        • 检查LoginWindow里面的登录
        • 如果登录成功,使用提供的参数启动MainWindow

        在看到 jdi 的答案之前,我开始编写一个简单的示例。我不妨把它放在这里。

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

        【讨论】:

        • 是的,这与我的方法几乎完全相同,除了您将逻辑移至 main 而不是让 MainWindow 管理它。每种方式都行之有效。
        【解决方案5】:

        不管你的描述如何,我认为你的 LoginWindow 应该是一个 QDialog,你的 StuffWIdow 应该是 MainWindow,并且像这样运行......

        1. 应创建您的 StuffWindow MainWindow(未显示)
        2. 调用login() 方法创建并执行您的登录 QDialog 作为应用程序 MODAL 对话框
        3. 现在启动 app.exec_() 事件循环,等待用户与登录交互
        4. 用户与登录对话框交互,对话框关闭的结果将允许您的应用检查其值并选择显示其主界面。

        这里是一个简短的大纲:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多