I’m trying to integrate this technique with fbs but can’t seem to make it work. It doesn’t see my .ui file. Can you please explain how to set this up in fbs?
@MJ_McLaren Its probably due to the way the file is being called i learned the below techniques from trial and error and loading it this way loads it from a relative path which works in fbs when run from source in pycharm and fbs and when frozen
This would be the fbs way to do that tutorial with fbs in mind and if the mainwindow.ui file is in same path as main.py and also in “src/main/resources/base/mainwindow.ui”
# from fbs_runtime.application_context import is_frozen # from fbs_runtime.excepthook.sentry import SentryExceptionHandler import os import sys import requests from PyQt5 import uic, QtWidgets from pyqtgraph import PlotWidget import pyqtgraph as pg from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtWidgets import QApplication from fbs_runtime.application_context.PyQt5 import ApplicationContext, \ cached_property class AppContext(ApplicationContext): def run(self): version = self.build_settings['version'] QApplication.setApplicationName("App Name") QApplication.setOrganizationName("Some Corp") QApplication.setOrganizationDomain("example.com") current_version = version self.main_window.setWindowTitle("App Name v" + version) self.main_window.show() return self.app.exec_() @cached_property def main_window(self): return MainWindow(self) qtCreatorFile = os.path.join(os.path.abspath(os.path.dirname(sys.argv)), "mainwindow.ui") # Type your file path Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile) class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, ctx): super(MainWindow, self).__init__() self.ctx = ctx self.setupUi(self) #Put all your custom signals slots and other code here. import sys if __name__ == '__main__': appctxt = AppContext() exit_code = appctxt.run() sys.exit(exit_code)
I use this same approach in my fbs app with lots of UI files.
Setting up Application context with fbs and UI was a royal pita to learn but once you have a nice skeleton def save a copy somewhere cause it comes in handy. You will want to then define as much as possible in the UI file vs the python main so its cleaner and just have the logic in the python.
For reference of my setup
Main root is
For FBS stuff i also copy same files into this path so bundled properly when compiled
To load say the about.ui file from “src/main/resources/base/ui/about.ui” via relative path “ui/about.ui” with FBS even when frozen
about_ui = os.path.join(os.path.abspath(os.path.dirname(sys.argv)), 'ui', "about.ui") uic.loadUi(about_ui, self)
This handy trick also works for images too
loads my app logo in about dialog from relative ‘images/chevron_logo.png’
self.about_app_logo.setPixmap( QPixmap(os.path.join(os.path.abspath(os.path.dirname(sys.argv)), 'images', 'chevron_logo.png')))
The best part of joining paths and that code is always works from where code is executed even when frozen and its OS agnostic so works for joining same path on Windows with path separators \ like it does with / on linux and Mac. One of the things i wish i had learned at beginning of my python adventures.
this equals path of current running script
This is joining current path + ‘ui’ folder + ‘about.ui’ filename
os.path.join(os.path.abspath(os.path.dirname(sys.argv)), 'ui', "about.ui")
To experiment can use the below snippet and adjust
import os import sys print(os.path.abspath(os.path.dirname(sys.argv))) print(os.path.join(os.path.abspath(os.path.dirname(sys.argv)), 'ui')) print(os.path.join(os.path.abspath(os.path.dirname(sys.argv)), 'ui', "about.ui"))
/home/username/.config/JetBrains/PyCharm2020.1/scratches /home/username/.config/JetBrains/PyCharm2020.1/scratches/ui /home/username/.config/JetBrains/PyCharm2020.1/scratches/ui/about.ui
To understand the resource files and structure for when its frozen also see.
Hopefully that helps some and provides some context.
Screenshots for visualization.