Pass a .ui file created with Qt designer to fbs for packaging

1.3k views Asked by At

i have written a Python application and I would like to distribute it. I have built a GUI on top of it and works fine so far. I use the following to set up the GUI:

qtCreatorFile = "gui.ui" 
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        # Initialize parent PyQt classes
        QtWidgets.QMainWindow.__init__(self)
        self.setupUi(self)
        (....)

The application starts with the following:

if __name__ == "__main__":
     app = QtWidgets.QApplication(sys.argv)
     window = MyApp()
     window.show()
     sys.exit(app.exec_())  

If I understand correctly, for using the 'gui.ui' file withing packaging with fbs, I should load it as a resource. So I use these as a modification:

from fbs_runtime.application_context import ApplicationContext, cached_property #added to imports)

class AppContext(ApplicationContext):           # Subclass ApplicationContext
    def run(self):
        qtCreatorFile=self.get_design()    # to get the .ui file
        Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
        window = MyApp()
        version = self.build_settings['version']
        window.setWindowTitle("EPANET parser v" + version)
        window.show()
        return self.app.exec_()

    def get_design(self):
        qtCreatorFile=self.get_resource("gui.ui") # It is in the correct src\main\resources path
        return qtCreatorFile

    @cached_property # all tutorials suggest this , but don't understand why. ???
    def main_window(self):
        return MainWindow(self)

The fbs application should start with the following replacement of if __name__ == '__main__:':

if __name__ == '__main__':
    appctxt = AppContext()    
    exit_code = appctxt.app.exec_()
    sys.exit(exit_code)

However, I get the following error: Traceback (most recent call last): File "C:\Users\....src\main\python\main.py", line 61, in <module> class MyApp(QtWidgets.QMainWindow, Ui_MainWindow): NameError: name 'Ui_MainWindow' is not defined

I understand that the MyApp is inheriting from the Ui_MainWindow that is defined inside the AppContext class now, and MyApp cannot reference it. Any help will be greatly appreciated!

1

There are 1 answers

4
eyllanesc On BEST ANSWER

Instead of using uic.loadUiType() you can use uic.loadUi() that just populates the window by passing the .ui path

main.py

from fbs_runtime.application_context.PyQt5 import ApplicationContext, cached_property

import sys

from mainwindow import MyApp


class AppContext(ApplicationContext):
    def run(self):
        self.window.resize(640, 480)
        self.window.show()
        return appctxt.app.exec_()

    def get_design(self):
        qtCreatorFile = self.get_resource("gui.ui")
        return qtCreatorFile

    @cached_property
    def window(self):
        return MyApp(self.get_design())


if __name__ == "__main__":
    appctxt = AppContext()
    exit_code = appctxt.run()
    sys.exit(exit_code)

mainwindow.py

from PyQt5 import QtWidgets, uic


class MyApp(QtWidgets.QMainWindow):
    def __init__(self, ui, parent=None):
        super().__init__(parent)
        uic.loadUi(ui, self)
        # ...
└── src
    ├── build
    │   └── settings
    │       ├── base.json
    │       ├── linux.json
    │       └── mac.json
    └── main
        ├── icons
        │   ├── base
        │   │   ├── 16.png
        │   │   ├── 24.png
        │   │   ├── 32.png
        │   │   ├── 48.png
        │   │   └── 64.png
        │   ├── Icon.ico
        │   ├── linux
        │   │   ├── 1024.png
        │   │   ├── 128.png
        │   │   ├── 256.png
        │   │   └── 512.png
        │   ├── mac
        │   │   ├── 1024.png
        │   │   ├── 128.png
        │   │   ├── 256.png
        │   │   └── 512.png
        │   └── README.md
        ├── python
        │   ├── main.py
        │   └── mainwindow.py
        └── resources
            └── base
                └── gui.ui