我正在使用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文件?或者有什么替代方法可以实现我想要实现的目标吗?
好吧,我认为你可以做两个现实的事情之一:
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兼容。
由于您已经直接加载了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文件,您始终需要使用资源文件才能将图标打包到程序中。出于可移植性的原因,使用图标资源文件可能是一个很好的习惯。