用打包工具将做好的Pyqt程序打包成exe后发现引用的资源图片都显示不了?
是否遇到了和我一样的问题呢。google之后找到了方法,一种方法是在程序中引用外部资源,另外一种方法是将资源文件转换为py文件,然后引用py。下面我们详细来实现后者方法实现的过程
一. 生成资源文件
要把资源文件转换为py文件首先要有资源文件,我们打开Qt Designer,添加资源文件
保存好资源文件后缀是以 .qrc 结尾的,用notepad++查看.qrc文件发现该文件其实为XML
1 <RCC> 2 <qresource prefix="picture"> 3 <file>img/270r.png</file> 4 <file>img/440kb.png</file> 5 <file>img/firefox.png</file> 6 <file>img/notepad.png</file> 7 <file>img/python.png</file> 8 <file>img/cut.png</file> 9 <file>img/python.jpg</file> 10 <file>img/loading.gif</file> 11 </qresource> 12 </RCC>
二. 创建一个窗体
用Qt Designer 创建一个最简单的窗体
然后将.ui文件转换成 py文件
1 # -*- coding: utf-8 -*- 2 3 # Form implementation generated from reading ui file 'resource.ui' 4 # 5 # Created: Tue Jan 20 17:17:34 2015 6 # by: PyQt4 UI code generator 4.10.3 7 # 8 # WARNING! All changes made in this file will be lost! 9 10 from PyQt4 import QtCore, QtGui 11 12 try: 13 _fromUtf8 = QtCore.QString.fromUtf8 14 except AttributeError: 15 def _fromUtf8(s): 16 return s 17 18 try: 19 _encoding = QtGui.QApplication.UnicodeUTF8 20 def _translate(context, text, disambig): 21 return QtGui.QApplication.translate(context, text, disambig, _encoding) 22 except AttributeError: 23 def _translate(context, text, disambig): 24 return QtGui.QApplication.translate(context, text, disambig) 25 26 class Ui_resource(object): 27 def setupUi(self, resource): 28 resource.setObjectName(_fromUtf8("resource")) 29 resource.resize(400, 300) 30 31 self.retranslateUi(resource) 32 QtCore.QMetaObject.connectSlotsByName(resource) 33 34 def retranslateUi(self, resource): 35 resource.setWindowTitle(_translate("resource", "Form", None))
三. 转换资源文件
转换资源文件用的是Pyqt的pyrcc4 命令
1 pyrcc4 qrcfile.qrc -o pyfile.py
1.Pycharm集成pyrcc4
我们使用Pycharm来集成pyrcc4,这样更利于我们高效开发
首先在菜单里面找到 File => settings => Tools => External Tools (外边工具设置)
选择添加Add
Name 填写: Rcc2Py
Group: 自已任意填写,我填写的是PyQt4
下面的Options默认
在Tools settings 里面这样填写:
Program 就是你安装Pyqt4的路径
Parameters 是指转换的参数 $FileName$ -o $FileNameWithoutExtension$.py
Working directory 表示输出在当前的工作目录 $FileDir$
2.转换qrc为py
选择要转换的qrc文件,右键,找到group 为(PyQt4) 目录下的Rcc2Py
转换完成后,同级目录下就多出一个与qrc文件同命名的py文件,查看文件:
1 # -*- coding: utf-8 -*- 2 3 # Resource object code 4 # 5 # Created: 周二 一月 20 11:43:03 2015 6 # by: The Resource Compiler for PyQt (Qt v4.8.5) 7 # 8 # WARNING! All changes made in this file will be lost! 9 10 from PyQt4 import QtCore 11 12 qt_resource_data = " 13 x00x00x05x2b 14 x89 15 x50x4ex47x0dx0ax1ax0ax00x00x00x0dx49x48x44x52x00 16 x00x00x20x00x00x00x20x08x06x00x00x00x73x7ax7axf4 17 x00x00x00x04x67x41x4dx41x00x00xd6xd8xd4x4fx58x32 18 x00x00x00x19x74x45x58x74x53x6fx66x74x77x61x72x65 19 x00x41x64x6fx62x65x20x49x6dx61x67x65x52x65x61x64 20 x79x71xc9x65x3cx00x00x04xbdx49x44x41x54x58xc3xed 21 x57x6bx4cx93x57x18x3ex23x71xc9x32xe9x16x97xa8x54 22 x65x38x9dx02x15xf6x03x87x32x93x01x66x2cx5bx70xc4 23 x30xffx60xa2x2ex1ax3ax1dx4ex03xbax31x89x5bxb3x80 24 xd9x0cx84x02x19x58x1cx14x8bx85xb2x82x95x5exe4x66 25 x0bx8ex31xf8xc3x46xcbx2dx81x15xdcxa8xc2x1cx1bxb7 26 x6ax69x91xf2xeexbcx87xafx0cxdcxb8x0dx61xd9xb2x93 27 x3cxedx97xf3x7dxfdxdexe7xbcxefxf3x5ex4ax00x80xfc 28 x93x20xffx0ax02x74x09x28x44x14xd9x14x71x14x01x2b 29 x46x80xaexddx64xddxc6x66x22x4cxf8x95xc4x8bx47xc8 30 xa1xd3xf7xc8x8ex97x3bx38x32x61x2bx41x20x85x9cxbe 31 x30x48x2exddx80x19x40x32xabx79x4dxf4xbexfbx72x13 32 x68x64x06x91x04x5exa3x51xf4x06xeex85x47xf5xd0xbd 33 x83xcbx4dx20x9bx9dxf6x40x74x2fxbdx16x32x3dx20x89 34 x3fx48xa5x2cx1bx01x8cx31x79xc1xbbx9dx88x4bxc6xd7 35 xc6x26x0exa0x10xb9xfdx42xfexc5x2bx36x46x8cx12x5c 36 x4ex02x93xa7xa7xa7x0dxccxd3x39xb9x98x63x36x14x0a 37 ………………………… 38 ………………………… # 此处省略1000行 39 ………………………… 40 qt_resource_struct = " 41 x00x00x00x00x00x02x00x00x00x01x00x00x00x01 42 x00x00x00x00x00x02x00x00x00x01x00x00x00x02 43 x00x00x00x14x00x02x00x00x00x08x00x00x00x03 44 x00x00x00x4ex00x01x00x00x00x01x00x00x3ax1b 45 x00x00x00xcex00x00x00x00x00x01x00x09x24x4c 46 x00x00x00x9cx00x00x00x00x00x01x00x01x90xfe 47 x00x00x00x86x00x00x00x00x00x01x00x00xa3x09 48 x00x00x00x20x00x00x00x00x00x01x00x00x00x00 49 x00x00x00x6ax00x00x00x00x00x01x00x00x79x75 50 x00x00x00x34x00x00x00x00x00x01x00x00x05x2f 51 x00x00x00xb4x00x00x00x00x00x01x00x08x72xdb 52 " 53 54 def qInitResources(): 55 QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 56 57 def qCleanupResources(): 58 QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) 59 60 qInitResources()
该文件已经使用QtCore.qRegisterResourceData 对文件初始化注册,所以我们可以直接引用该文件
四. 引用资源py文件
py文件生成好了如何来引用使用呢?
说对了,引用就这么简单
1 import apprcc
使用的时候 冒号 “ : ” 加 图片的路径, 如:
1 :/img/firefox.png
运行试试,发现图片不显示,为什么呢,因为qrc文件添加过程中,我加了一个 “前缀” prefix。 所以,如果在qrc文件中不添加前缀 使用 :/img/firefox.png 是可以的,但添加了前缀生成的qrc文件 qresource标签会多一个属性
1 qresource prefix="picture"
在这里,正确的使用是:
:picture/img/firefox.png
完整的代码如下:
1 # -*- coding: utf-8 -*- 2 3 # Form implementation generated from reading ui file 'resource.ui' 4 # 5 # Created: Tue Jan 20 17:17:34 2015 6 # by: PyQt4 UI code generator 4.10.3 7 # 8 # WARNING! All changes made in this file will be lost! 9 10 from PyQt4 import QtCore, QtGui 11 12 try: 13 _fromUtf8 = QtCore.QString.fromUtf8 14 except AttributeError: 15 def _fromUtf8(s): 16 return s 17 18 try: 19 _encoding = QtGui.QApplication.UnicodeUTF8 20 def _translate(context, text, disambig): 21 return QtGui.QApplication.translate(context, text, disambig, _encoding) 22 except AttributeError: 23 def _translate(context, text, disambig): 24 return QtGui.QApplication.translate(context, text, disambig) 25 26 class Ui_resource(object): 27 def setupUi(self, resource): 28 resource.setObjectName(_fromUtf8("resource")) 29 resource.resize(400, 300) 30 31 self.retranslateUi(resource) 32 QtCore.QMetaObject.connectSlotsByName(resource) 33 34 def retranslateUi(self, resource): 35 resource.setWindowTitle(_translate("resource", "Form", None)) 36 37 38 import apprcc 39 class showresource(QtGui.QWidget): 40 def __init__(self): 41 super(showresource, self).__init__() 42 self.ui_resource = Ui_resource() 43 self.ui_resource.setupUi(self) 44 self.setWindowTitle('ResourceToPy') 45 46 palette1 = QtGui.QPalette(self) 47 palette1.setBrush(self.backgroundRole(), QtGui.QBrush(QtGui.QPixmap(':picture/img/firefox.png'))) 48 49 self.setPalette(palette1) 50 51 # 重载keyPressEvent , 当按下Esc退出 52 def keyPressEvent(self, event): 53 if event.key() ==QtCore.Qt.Key_Escape: 54 self.close() 55 56 57 58 59 if __name__ == "__main__": 60 import sys 61 app = QtGui.QApplication(sys.argv) 62 resource = showresource() 63 resource.show() 64 sys.exit(app.exec_())
五. 打包运行
我使用的是Pyinstaller打包成单一的exe,运行exe查看效果