如何在使用py2exe时包含ui和图像文件?

问题描述 投票:5回答:1

我正在使用Python 2.7和PySide 1.1.2开发一个项目。我的代码在我的GNU / Linux上没有任何问题,但我想分发Windows(7和8)。我不能指望用户安装Python和PySide,所以我决定使用py2exe(我也试过cx_freeze和pyinstaller)。

首先,这是我的文件树:My Project on GitHub

我创建了一个setup.py,这里是:

# -*- coding: utf-8 -*-

from distutils.core import setup
import py2exe

setup(
    console=['bin/metusuite.py'],
    name='metusuite',
    version='0.1',
    author='H. Gökhan Sarı',
    author_email='[email protected]',
    packages=['metusuite_libs'],
    package_dir={'metusuite_libs': 'metusuite_libs'},
    package_data={'metusuite_libs': ['ui/*', 'images/*']},
    scripts=['bin/metusuite.py'],
    url='https://github.com/th0th/metusuite/',
    license='LICENSE.txt',
    description='METU Suite.',
    long_description=open('README.md').read(),
)

我跑的时候

setup.py py2exe

它成功地在'dist'文件夹中构建了metusuite.exe,但是,由于应用程序依赖于外部用户界面文件 - 使用Qt Designer创建 - 并且找不到它们,我收到错误:

Designer: An error has occurred while reading the UI file at line 1, column 0: Premature end of document.
Traceback (most recent call last):
  File "metusuite.py", line 38, in <module>
  File "metusuite_libs\msCafeteriaMenu.pyc", line 37, in __init__
  File "metusuite_libs\msCafeteriaMenu.pyc", line 17, in __init__
RuntimeError: Unable to open/read ui device

我无法弄清楚我应该如何将* .ui文件(也有一些.png图标)添加到该结构中。我在考虑将.ui文件转换为Python代码,然后当我需要添加一些图标时,我会遇到同样的问题。

因此,如何在py2exe结构中添加我的ui和png文件?或者有什么替代方法可以实现我想要实现的目标吗?

windows py2exe pyside
1个回答
10
投票

好吧,我认为你可以做两个现实的事情之一:

  1. 使用pyside-uic将.ui文件编译为.py文件并修改代码以对用户界面进行条件加载py文件,并将png文件放在Qt资源文件中
  2. 用你的ui文件创建一个Qt资源文件,用pyside-rcc编译,然后使用QtUiTools或类似的进程加载ui文件

pyside-uic

我更喜欢使用pyside-uic方法来加载ui文件,因为它是将ui文件加载到与我在C ++中的Qt知识相关的程序中最直接的方法。 pyside-uic包含在PySide应用程序中,对我来说,它可以在我的Python安装的Scripts目录中找到,例如: C:\Python27\Scripts\pyside-uic.exe。记下C ++编译如何处理ui文件,我通常编译我的ui文件,使其名称为ui_ [ui文件的名称] .py:

C:\Python27\Scripts\pyside-uic mainwindow.ui > ui_mainwindow.py

在生成的.py文件中,pyside-uic创建一个名为与Ui前面的ui文件的基类同名的类。因此,例如,如果您创建了一个mainwindow.ui,其中包含名为MainWindow的类的定义,则创建的类将为Ui_MainWindow。如果ui文件定义了一个名为SourceWindow的类,则.py文件中的类为Ui_SourceWindow。在Qt Designer中,您可以通过在对象树的根元素中设置objectName来设置类名(在窗口的右上角)。

使用您的文件cafeteria_menu,ui和dialog_login.ui,您将获得派生类Ui_cafeteria_menu和Ui_dialog_login。

生成.py文件后,可以将其导入到窗口小部件的定义文件中,并使用Ui文件中类的setupUi方法使用它。

from PySide import QtCore, QtGui
from ui_mainwindow import Ui_MainWindow

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

一旦为该类定义了ui,就需要通过self.ui访问该小部件的所有连接和ui元素

        self.ui.lineEdit.textChanged[str].connect(self.processText)

由于您必须将.png文件放在Qt资源文件中,我将在下一节中讨论它。

pyside-rcc

pyside-uic一样,pyside-rcc包含在PySide应用程序中,虽然我的是在Python的site-packages目录而不是Scripts中(如果它在你的同一个地方,你可以随时复制它)。

C:\Python27\lib\site-packages\PySide\pyside-rcc.exe

在编译Qt资源文件之前,必须先使用其中一个Qt工具创建它。我使用Qt Creator,因为它可以在一个应用程序中执行几乎所有与Qt相关的功能。 Qt Resource System的文档显示资源文件实际上只是一个XML文件,它定义了资源系统的文件路径和内部路径。您可以根据需要设置和组织文件,但在编译时,资源文件中定义的所有文件必须位于文件的同一目录或子目录中。一旦定义了资源文件,就需要使用pyside-rcc.exe将其编译为.py文件。我通常将资源文件命名为与项目相同,并将所有内容保存在一个资源文件中,以便更简洁地处理资源。

C:\Python27\lib\site-packages\PySide\pyside-rcc.exe -py2 MyProject.qrc > MyProject_Resources.py

-py2开关定义应该为Python 2.x格式化文件的输出。如果您正在使用Python 3.x或计划将来使用它,您可以使用-py3开关,结果将与Python 3.x兼容。

Putting it all together

由于您已经直接加载了ui文件QUiLoader,因此您只需要重构QUiLoader语句以加载从资源系统打开ui资源的QFile。要使用资源系统中的文件,您需要做的就是将您的Resource .py文件(从pyside-rcc生成的文件)导入到程序的主脚本文件中,并且资源文件中的最后一行是对qInitResources()初始化要在整个程序中使用的资源。要使用QFile加载文件,请使用以“:”开头的路径,然后引用资源文件中定义的路径。您可以创建一个文件msResources.qrc,它具有ui和将您的ui和png文件定义为子类别的图像。

所以,如果您的资源文件看起来像这样

/ui
    cafeteria_menu.ui
    dialog_login.ui
/images
    cafeteria-menu.png
    exit.png
    logo.png
    mail-fetch.ong

而且,如果你想加载这些文件,你只需要像这样创建一个QIcon或QFile:

cafeteriaMenuIcon = QtGui.QIcon(":/images/cafeteria-menu.png")
cafeteriaMenuUi = QtCore.QFile(":/ui/cafeteria_menu.ui")

在msCafeteriaMenu中的GUICafeteriaMenu代码中使用时,我只需更改GuiCafeteriaMenu的__init__方法来加载并使用资源中的ui文件:

uiFile = QFile(":/ui/cafeteria_menu.ui")
uiFile.open(QFile.ReadOnly)
UiLoader.load(uiFile, self)
uiFile.close()

我可能会将pyside-rcc的输出放入metsuite_libs包中,类似于msResources.py,并将__init__.py文件中的msResources文件作为包的一部分导入。这样,一旦你创建了.py文件并将其导入你的程序,额外的文件将封装在你的包中,你不需要更改你的setup.py文件。在进行py2exe转换之前,运行重构程序应该正常工作。此外,无论您如何处理ui文件,您始终需要使用资源文件才能将图标打包到程序中。出于可移植性的原因,使用图标资源文件可能是一个很好的习惯。

© www.soinside.com 2019 - 2024. All rights reserved.