【问题标题】:PyQT5 ui file, does not load properly from the executable filePyQT5 ui 文件,无法从可执行文件正确加载
【发布时间】:2022-12-03 14:07:46
【问题描述】:

我正在通过构建与设计器的接口并导出到 .ui 文件来构建 PyQt5 应用程序。后者然后由我的主类加载。这是我的源代码示例,名称为main.py

主程序

import os.path
import PyQt5.QtWidgets as qtw
from PyQt5.uic import loadUi
import sys

class MainUI(qtw.QMainWindow):
    def __init__(self, parent=None):
        super(MainUI, self).__init__()
        self._ui_path = os.path.dirname(os.path.abspath(__file__))
        loadUi(os.path.join(self._ui_path, 'main.ui'), self)

if __name__ == "__main__":
    # Create the application
    app = qtw.QApplication(sys.argv)
    # Create and show the application's main window
    win = MainUI()
    win.show()
    sys.exit(app.exec())

主界面

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>320</width>
    <height>240</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>110</x>
      <y>100</y>
      <width>88</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>ok</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>320</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

我通过给pyinstaller -F -w main.py生成一个带有pyinstaller的可执行文件。

一开始,可执行文件应该与 ui.xml 位于同一文件夹中。我已经按照here的回答更改了loadUI

当我现在运行可执行文件时,它会给我一条带有以下回溯的错误消息:

Traceback (most recent call last):
  File "main.py", line 17, in <module>
    win = MainUI()
  File "main.py", line 11, in __init__
    loadUi(os.path.join(self._ui_path, 'main.ui'), self)
  File "PyQt5\uic\__init__.py", line 238, in loadUi
  File "PyQt5\uic\Loader\loader.py", line 66, in loadUi
  File "PyQt5\uic\uiparser.py", line 1020, in parse
  File "xml\etree\ElementTree.py", line 1202, in parse
  File "xml\etree\ElementTree.py", line 584, in parse
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\username\\AppData\\Local\\Temp\\_MEI187162\\main.ui'

发生的事情是,在运行 .exe 文件后,会创建一个包含一些 dll 文件的临时目录,程序会尝试在该目录中找到 .ui 文件,但没有成功。如何将可执行文件定向到 .ui 文件所在的位置?

【问题讨论】:

  • 如果您真的决定使用单文件捆绑的可执行文件,@RichardSmith 的答案看起来不错。我质疑单文件提议的价值,因为它保证 (1) 运行速度较慢并且 (2) 占用更多磁盘空间。可能有一个我不知道的好用例,但我通常只分发整个 dist 文件夹。
  • 据我所知,你至少在(1)是对的。对于dist 文件夹,我们是否应该使用“简单”loadUi('main.ui', self) 加载.ui
  • 是的,loadUi 应该可以在您的 EXE 文件中正常工作。我在我的大部分应用程序中使用 loadUiType。您只需要通过将 .ui 文件放入 spec 文件的 added_files 部分来确保它包含在您的 dist 文件夹中。

标签: python pyqt5


【解决方案1】:

将其添加到程序顶部的某处:

import sys
import os

if getattr(sys, 'frozen', False):
    RELATIVE_PATH = os.path.dirname(sys.executable)
else:
    RELATIVE_PATH = os.path.dirname(__file__)

然后当你去打电话loadUi()时:

self._ui_path = RELATIVE_PATH + "/ui_path"  # Update this as needed

loadUi(os.path.join(self._ui_path, 'main.ui'), self)

当程序在别处编译和运行时,目录会变得有点奇怪。看看这是否适合您,如果不适合,请告诉我,我可以进一步提供帮助。

【讨论】:

  • 它起作用了,我现在不知道 frozen 属性。好像是pyinstaller的东西。答案还建议使用目录ui_path作为我们.exe所在位置的子目录,但可以轻松配置这部分。
【解决方案2】:

我从 PyQt5 版本 5.15.7 返回到版本 5.15.1按命令“pip 安装 PyQt5==5.15.1“。我的问题解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 2012-09-24
    • 2017-11-17
    相关资源
    最近更新 更多