Search code examples
pythonqt-designerpyside2

How to create a Widget using .ui file?


I'd like to create a widget inside a MainWindow that gets its design from a file created with QtDesigner.

  • the .ui file I created is test.ui
  • I have a MainWindow instance inheriting from QMainWindow that will create a stacked widget with many widgets inside it. For simplicity in this example, it will create just a widget as central widget.
  • The My Widget instance inside the MainWindow is the one that has to grab its design from the .ui file

As it is, the application shows a blank window

Here is the code:

from PySide2.QtWidgets import QMainWindow, QApplication, QDesktopWidget, QWidget
from PySide2.QtCore import QCoreApplication, Qt

from PySide2.QtUiTools import QUiLoader
from PySide2.QtCore import QFile

class MyWidget(QWidget):
    def __init__(self, parent=None):        
        super(MyWidget, self).__init__(parent)

    ui_file = QFile("test.ui")
    ui_file.open(QFile.ReadOnly)

    loader = QUiLoader()
    window = loader.load(ui_file)
    ui_file.close()


class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui_dim_percentage = 70/100
        self.initUI()

    def initUI(self):
        self.center()

        self.home_widget = MyWidget(self)
        self.setCentralWidget(self.home_widget)

        self.show()

    def center(self): # resizes the UI to a percentage of the screen and centers the widget

        screen_size = QDesktopWidget().screenGeometry()
        self.resize(screen_size.width()*self.ui_dim_percentage, screen_size.height()*self.ui_dim_percentage)

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


def main():

    app = QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

How should I correct the code?


Solution

  • The problem is that you are confusing concepts, when you use QUiLoader you are creating the window that in this case is the window variable that is a local variable, that is, the .ui does not fill in MyWidget.

    The solution is not to create the MyWidget class, just use the window variable.

    from PySide2.QtWidgets import QMainWindow, QApplication, QDesktopWidget
    from PySide2.QtCore import QFile
    from PySide2.QtUiTools import QUiLoader
    
    
    def create_widget():
        ui_file = QFile("test.ui")
        if ui_file.open(QFile.ReadOnly):
            loader = QUiLoader()
            window = loader.load(ui_file)
            ui_file.close()
            return window
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.ui_dim_percentage = 70 / 100
            self.initUI()
    
        def initUI(self):
            self.center()
    
            self.home_widget = create_widget()
            self.setCentralWidget(self.home_widget)
    
            self.show()
    
        # resizes the UI to a percentage of the screen and centers the widget
        def center(self):
    
            screen_size = QDesktopWidget().screenGeometry()
            self.resize(
                screen_size.width() * self.ui_dim_percentage,
                screen_size.height() * self.ui_dim_percentage,
            )
    
            qr = self.frameGeometry()
            cp = QDesktopWidget().availableGeometry().center()
            qr.moveCenter(cp)
            self.move(qr.topLeft())
    
    
    def main():
        import sys
    
        app = QApplication(sys.argv)
        ex = MainWindow()
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()