Using fbs to package a PyQt5 app, what could be the cleanest way to access resource files from non-GUI code?
In the example below, I made a simple PyQt5 app with one window containing one button. The button triggers a function that will read a .json
resource file and print its attribute message
in the console. The function print_data()
defined in logic.py should also work without the GUI app, for example to be used by other python scripts. Therefore, it cannot be move as a method of the MainWindow class.
It is easy and handy to use the application context's get_resource()
method to get the path to mainwindow.ui. Unfortunately, it cannot be used by print_data()
to get the path to static_data.json as the function has no access to the application context.
What would be the best solution?
Directory structure:
|-- src
| |-- main
| | |-- python
| | | |-- main.py
| | | |-- gui.py
| | | |-- logic.py
| | |-- resources
| | | |-- base
| | | | |-- mainwindow.ui
| | | | |-- static_data.json
Content of main.py
:
from fbs_runtime.application_context.PyQt5 import ApplicationContext
import sys
from gui import MainWindow
if __name__ == '__main__':
appctxt = ApplicationContext()
window = MainWindow(appctxt)
window.show()
exit_code = appctxt.app.exec_()
sys.exit(exit_code)
Content of gui.py
:
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import uic
from logic import print_data
class MainWindow(QMainWindow):
def __init__(self, context):
super().__init__()
# Loading the .ui file from the resources
self.ui = uic.loadUi(context.get_resource("mainwindow.ui"), self)
# Binding the button to the print_data function defined in logic.py
self.main_button.clicked.connect(print_data)
Content of logic.py
:
import json
def print_data():
# Getting the resource data filepath
filepath = "../resources/base/static_data.json"
# Processing the resource file
with open(filepath) as file:
data = json.load(file)
print(data["message"])
python
├── base.py
├── gui.py
├── logic.py
└── main.py
One possible solution is to create the context in a file where everyone can access that variable:
base.py
from fbs_runtime.application_context.PyQt5 import ApplicationContext
context = ApplicationContext()
Then it is used in the other classes:
gui.py
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import uic
from base import context
from logic import print_data
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Loading the .ui file from the resources
self.ui = uic.loadUi(context.get_resource("mainwindow.ui"), self)
# Binding the button to the print_data function defined in logic.py
self.main_button.clicked.connect(print_data)
logic.py
import json
from base import context
def print_data():
# Getting the resource data filepath
filepath = context.get_resource("static_data.json")
# Processing the resource file
with open(filepath) as file:
data = json.load(file)
print(data["message"])
main.py
import sys
from base import context
from gui import MainWindow
if __name__ == "__main__":
window = MainWindow()
window.resize(250, 150)
window.show()
exit_code = context.app.exec_()
sys.exit(exit_code)