代码之家  ›  专栏  ›  技术社区  ›  Ankit Tiwari

PyQt5如何将pyuic5生成的Python类添加到QStackedWidget中?

  •  0
  • Ankit Tiwari  · 技术社区  · 3 周前

    我有这个在我的 app.py :

    from PyQt5 import QtWidgets
    from screens import Ui_home, Ui_login_page
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            QtWidgets.QMainWindow.__init__(self)
            
            self.home = Ui_home()
            self.home.setupUi(self)
    
            self.login = Ui_login_page()
            self.login.setupUi(self)
            
            self.screens = QtWidgets.QStackedWidget()
            self.screens.addWidget(self.home)
            self.screens.addWidget(self.login)
    
            self.home.pushButton.clicked.connect(
                lambda: self.screens.setCurrentWidget(self.login)
            )
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication([])
        window = MainWindow()
        window.show()
        app.exec_()
    

    在上述代码中, Ui_home & Ui_login_page 屏幕是从生成的 *.ui 从PyQt5设计器生成的文件。当我运行此代码时,我会收到以下错误:

    self.screens.addWidget(self.home)
    TypeError: addWidget(self, w: Optional[QWidget]): argument 1 has unexpected type 'Ui_home'
    

    我知道 self.setCurrentWidget() 需要 QWidget ,以及从生成的代码 pyuic5 从Python继承类 object 。如何修复此问题,以便将主页和登录屏幕添加到堆栈小部件中?

    1 回复  |  直到 3 周前
        1
  •  1
  •   musicamante    3 周前

    以下内容是错误的或没有意义的:

    • Ui_home Ui_login_page 表单类 (从根本上讲,是基本的python对象),而不是小部件;
    • 使命感 setupUi(self) 不止一次是毫无意义的,因为它将重写当前小部件的UI;
    • 使命感 setCentralWidget() 多次将自动 摧毁 之前设置的小部件,对于堆叠的小部件来说,这显然是错误的,因为它应该允许切换回之前显示的“页面”;

    将堆叠的小部件作为中心小部件,然后创建适当的QWidget实例并调用 setupUi() 在它们中的每一个上,最后将这些小部件添加到堆叠的小部件中:

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            
            self.screens = QtWidgets.QStackedWidget()
            self.setCentralWidget(self.screens)
    
            self.home = QtWidgets.QWidget()
            self.home_ui = Ui_home()
            self.home_ui.setupUi(self.home)
    
            self.login = QtWidgets.QWidget()
            self.login_ui = Ui_login_page()
            self.login_ui.setupUi(self.login)
            
            self.screens.addWidget(self.home)
            self.screens.addWidget(self.login)
    
            self.home_ui.pushButton.clicked.connect(
                lambda: self.screens.setCurrentWidget(self.login)
            )
    

    请注意,更合适的方法(也在关于 using Designer )是使用 多重继承 反对 作文 (如上所示);这种方法提供了更好的模块化,因为每个“页面”都有自己的UI元素作为实例属性,从而避免了进一步的 ui 对象

    class HomePage(QtWidgets.QWidget, Ui_home):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setupUi(self)
    
    
    class LoginPage(QtWidgets.QWidget, Ui_login_page):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setupUi(self)
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            
            self.screens = QtWidgets.QStackedWidget()
            self.setCentralWidget(self.screens)
    
            self.home = HomePage()
            self.login = LoginPage()
            
            self.screens.addWidget(self.home)
            self.screens.addWidget(self.login)
    
            # note that now it's "self.home", not "self.home_ui"
            self.home.pushButton.clicked.connect(
                lambda: self.screens.setCurrentWidget(self.login)
            )
    

    在上面的代码中,差异似乎很小(有争议的是,既没有意义,也不必要冗长),但关键是为每个页面或容器小部件创建一个子类可以实现和调试正确而简单(请参阅 encapsulation ),例如添加自定义信号、创建内部函数以及简化对对象属性的访问的可能性。