Search code examples
pythonpyqtpysideqt-designerqt-resource

Common resource file in PyQt/ PySide and resource file location


When a resource file is created via Qt Designer in a Form, the python code generated by the Qt Designer includes the following import statement:

import icons_rc

This import statement is same irrespective of the qrc file location (say shared location \Modules\ZA\RES\ or ui location \Modules\ZA\MDH).

The generated form works only if the generated python file for qrc file is in same location as form; else it raises the error:

  File "S:\...\Modules\ZA\MDH\ui_BObj.py", line 25, in <module>
      import icons_rc
  ModuleNotFoundError: No module named 'icons_rc'

This implies saving all images and compiled qrc file in same location as the UI/Form folder. I used PySide6 with pyside6-rcc and I believe this behaviour is same in PyQt as well.

Does this mean that qrc file for every UI form must be created in the respective locations, even if these forms use same common icon set?

All documentation/ posts on this topic talks about the qrc file format and compiler, but there is no indication on location of the resource files. Is it not possible to create a shared/ common icons qrc file in one location, compile it and then use it in different UI forms in different locations?


Solution

  • The resources files/qrc file do not need to be in the ui/form folder. If the right project structure is used, there should be no problems.

    The designer/resource/qrc files can all go in the top level folder of the project: i.e. outside of the python package tree (which should only ever contain python modules). The --from-imports option should then be used when generating the ui modules, which can all go in a sub-package within the main python package tree, with the compiled resource modules going alongside them in the same sub-package. This will ensure the imports all work correctly - so long as the main.py script is located outside of the package, in the immediate parent folder.

    Once the final project structure has been determined, a makefile (or equivalent) could also be added at the top-level of the project that will execute whenever the program is run during development. This makefile could have a target that calls pyuic and pyrcc with the relevant src/dest paths, which will ensure any changes to the designer/resource/qrc files are always immediately reflected in the compiled ui/resource modules.

    A typical project structure might look something like this:

    project/
        designer/
            mainwindow.ui
            dialog.ui
        icons/
            logo.png
        LICENSE
        Makefile
        main.py
        prog.sh
        resources.qrc
        run.sh
        package/
            __init__.py
            app.py
            mainwindow.py
            dialog.py
            ui/
                __init__.py
                mainwindow_ui.py
                dialog_ui.py
                resources_rc.py
    

    (The prog.sh file is a simple shell script that starts the program, and is part of the main installation. The run.sh file is another shell script used only during development that - amongst other things - calls make before starting the program).

    PS: for a more detailed look at project structure, see this answer.