Your bug is the line engine.load('./UI/main.qml') (although the issue is masked by the fact that Qt doesn’t raise an error if it can’t load a file). Relative paths to locate application resources are not portable. I suggest you change that line to:
qml_path = './UI/main.qml' if not os.path.exists(qml_path): raise FileNotFoundError(qml_path) engine.load(qml_path)which will not fix your issue but it will give you a proper error message. Then read the docs for what qml_path should really be set to.
I homed in on it because any piece of code that uses a relative path to locate an application resource is broken (it’s relative to your current working directory which could be anywhere, not the application root, but IDEs hide this bug by setting your current working directory to the location of your code) and that false assumption gets flushed out pretty quickly when you run PyInstaller on it. If you’re not convinced, try opening or cd-ing a terminal somewhere far away from your original python code and running python /full/path/to/your/code.py. I expect that you’ll get the same error.
To be clear, what I think is happening is that Qt can’t find that QML file, whether you correctly packaged it or not, for the reasons described above. Qt doesn’t raise an error (although it does print a warning) so the code continues on but it never managed to load any UI objects from the QML file so engine.rootObjects() is an empty list and that’s why you’re getting an IndexError on that line.