PySide里如何加载图片资源

来源:互联网 发布:boost.python简明教程 编辑:程序博客网 时间:2024/06/14 13:35

本文大部分内容转载网络高手。针对PySide做了一点点说明      

Qt中使用图片资源,用得最多的就是图标了。静态图标或者图片一般这样加载:

      1. 编写qt resource文件,格式大致如下     

//--------------------images.qrc----------------------//
       <!DOCTYPE RCC><RCC version="1.0">
       <qresource prefix="/">
            <file>images/quit.png</file>
            <file>images/login.png</file>
            <file>images/open.png</file>
      </qresource>
      </RCC>



      2. 使用pyrcc4编译qt resource,生成py文件(如果是C++版本的话,使用rcc)
      pyrcc4 images.qrc -o images_rc.py

 

                             对于PySide来说的话,使用的是pyside-rcc


      3. 在程序中import images_rc,然后就可以使用了,  比如,为open菜单添加一个图标     

self.actionOpen = QtGui.QAction(self)
self.actionOpen.setIcon( QtGui.QIcon(":/images/open.png") )


      这种方法的特点就是肯定不会出错,即使用py2exe打包后,而且兼容性很好。但是不足是程序会变大,因为图片资源都静态编译到二进制程序中去了。


      另外一种加载图片或者图标的方法是我在做QZone的爬虫时遇到的问题:登陆QZone需要验证码,验证码可以通过访问腾讯的固定网址刷新,通过python的urllib/urllib2可以很容易下载下来手动输入,但是需要做到GUI里面的话,因为图片随时可以刷新,就不能编译成静态的二进制了。查了一下Qt的文档,发现QPixmap这个类可以直接从硬盘上的文件加载,文档中是这样描述的:
      ----------------------------------------------------------      
     
QPixmap::QPixmap ( const QString & fileName, const char * format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor )
      Constructs a pixmap from the file with the given fileName. If the file does not exist or is of an unknown format, the pixmap becomes a null pixmap.
      ...
      The file name can either refer to an actual file on disk or to one of the application's embedded resources. See theResource System overview for details on how to embed images and other resource files in the application's executable. 
      ----------------------------------------------------------
      这个fileName既可以是qt resource的文件,也可以是一个物理文件,所以就解决了我的问题:我先将验证码下载下来,然后实例化一个QPixmap对象,生成一个QIcon,添加到一个Button上就可以了:

pixmap = QtGui.QPixmap( 'verifcode.jpg' )
icon = QtGui.QIcon( pixmap )
self.verifCodeButton.setIcon( icon )


      不过后来发现QPixmap还有两个重载的函数loadFromData:    
      bool loadFromData ( const uchar * data, uint len, const char * format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor )
      bool loadFromData ( const QByteArray & data, const char * format = 0, Qt::ImageConversionFlags flags= Qt::AutoColor )
      因为我从url请求得到的图片数据本来就是二进制的数据,先是通过write生成jpg文件,再用QPixmap加载的,能不能直接把从url请求得到的数据直接load进去呢?因为第一个函数需要知道字节长度,查了下QByteArray的定义,我选择第二个函数,结果一试就成功啦,代码如下:

pixmap = QtGui.QPixmap()
imgdata = self.reqVerifCode()   # req the image data of verify code
bool = pixmap.loadFromData( QtCore.QByteArray(imgdata) )
if bool:
    icon = QtGui.QIcon( pixmap )
    self.veriCodeButton.setIcon( icon )

else:

    QtGui.QMessageBox.warning( None, u'警告', 
                    u"<font color='red'>加载验证码失败</font>" )


      正当我高兴之余,用py2exe打包后,发现我的button显示不出来图片,我开始以为程序有问题,但是直接用python.exe来执行明明就work得很好的。在确定代码没有问题后,我开始怀疑自己的setup.py有问题,我不确定是不是缺了某些库没加进去。于是Google之,关键词'py2exe Pixmap',相关信息较少,不过这个问题貌似有人碰到过,昨晚试了好几种方法,都没有得到解决。今天终于在这个地址找到了解决办法:
      You may try creating folder "imageformats" in the folder with your binary app and add DLLs from PyQt4 imageformats folder ( C:\Python26\Lib\site-packages\PyQt4\plugins\imageformats\. )

      就是把
PyQt4\plugins\imageformats\文件夹复制到你py2exe打包后可执行文件的目录下,其实我后来发现,imageformats里有6个dll文件,分别是qgif4.dll,qico4.dll,qjpeg4.dll,qmng4.dll,qsvg4.dll和qtiff4.dll,我猜想都是些使用图片资源需要的动态链接库,只需要保留qjpeg4.dll就可以了,因为我的验证码使用的是jpg的格式。修改setup.py文件后重新打包,至此,该问题得以圆满解决。

      先show一下我的QTricker:


还有我的RTK


Qt资源体系采用平台独立机制来存储应用程序执行时的二进制文件。这种机制在应用程序需要一些确定的文件(图标、翻译文件等等)而且又不想冒丢失文件的风险时是有用的。

        资源体系依赖于 qmake, rcc (Qt's resource compiler), 和 QFile 的紧密协作。Qt 3 的 qembed 工具和 image collection 机制被废除。

        Resource Collection Files (.qrc)

与应用程序关联的应用程序由 .qrc 文件来指定,它用XML记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问资源。

        一个.qrc 文件的例子:

<!DOCTYPE RCC><RCC version="1.0">

<qresource>

     <file>images/copy.png</file>

     <file>images/cut.png</file>

     <file>images/new.png</file>

     <file>images/open.png</file>

     <file>images/paste.png</file>

     <file>images/save.png</file>

</qresource>

</RCC>

        .qrc 文件中列出的资源文件是程序的源码树的一部分。指定的路径是 .qrc 文件所在目录的相对路径。注意,列出的资源文件必须位于 .qrc 文件所在目录或者其子目录下。

        资源数据也能被编译进二进制文件中,因此应用程序代码可以立即访问;也可以创建一个二进制资源,稍后在程序中登记了资源体系的代码中指定。

       缺省时,程序可以用资源在源码树中的名称加一个 :/ 前缀来访问它。例如,在程序的源码树中是 images/cut.png 的文件可以通过 :/images/cut.png 来访问。

       但也可以用 file 标签中的 alias 属性来指定

       <file alias="cut-img.png">images/cut.png</file>

       这时该文件可以通过 :/cut-img.png 来访问。也可以在 .qrc 文件中用 qresource 标签的 prefix 属性:它可以为 .qrc 文件中所有文件指定一个前缀

<qresource prefix="/myresources">

     <file alias="cut-img.png">images/cut.png</file>

</qresource>

       这时该文件可以用 :/myresources/cut-img.png 访问。

      有些资源,像翻译文件和图标,需要随着用户的本地配置而变化。这可以在 qresource 标签的 lang 属性中指定一个合适的本地化字串来实现。例如:

<qresource>

     <file>cut.jpg</file>

</qresource>

<qresource lang="fr">

     <file alias="cut.jpg">cut_fr.jpg</file>

</qresource>

       如果用户的本地化设置是 French (也就是说,QLocale::system().name() returns "fr_FR"),:/cut.jpg 就会引用 cut_fr.jpg 图像。对于其他本地化设置,仍然用 cut.jpg 。

       本地化字串的使用格式参见 QLocale 文档。

      使用外部二进制资源

      为创建一个外部二进制资源,需要通过向 rcc 传递 -binary 开关来生成资源数据(一般是.rcc扩展名)。然后可以用 QResource API 来注册资源。例如,一个 .qrc 文件指定的资源数据集可以用下面方法编译:

       rcc -binary myresource.qrc -o myresource.rcc

       应用程序中,用下面的代码注册资源: QResource::registerResource("/path/to/myresource.rcc");

       Compiled-In Resources

      必须在应用程序的 .pro 文件中指定.qrc 文件, qmake 才能知道并将资源编译进二进制文件。例如:

      RESOURCES  +  = application.qrc

      qmake 将产生make规则来生成一个叫做 qrc_application.cpp 的文件并把它链接到应用程序中。该文件中,图像和其他资源的所有数据被以压缩二进制数据存进静态C++数组中。 .qrc 文件被改变或者它引用的文件中的某一个被改变时, qrc_application.cpp 自动重新生成。若你没有使用 .pro 文件,你也可以手动调用 rcc 或者在你的编译系统中添加创建规则。

      通常,Qt直接将数据存储在可执行文件中,甚至在Windows和Mac OS X这些提供资源本地支持的操作系统中也是这样。这可能会在未来的Qt版本中改变。

       Using Resources in the Application

       应用程序中,绝大多数地方都可以用资源路径代替原始文件系统路径。尤其是在 QIcon, QImage, or QPixmap 构造器中可以传递资源路径来代替文件名称:

     cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);

在内存中,资源被用资源对象树来描述。该树在启动时自动构建并用QFile来解析资源路径。可以用":/" 初始化的 QDir 来从资源树的根部开始浏览。

      Qt资源支持搜索路径列表概念。若用 ":"代替":/"做前缀来引用一个资源,资源将被用搜索路径列表查询。启动时搜索路径列表是空的,调用 QDir::addResourceSearchPath() 可以添加路径。

If you have resources in a static library,必须用.qrc 文件的base name作参数调用 Q_INIT_RESOURCE() 来强制初始化资源。例如:

     int main(int argc, char *argv[])

     {

         QApplication app(argc, argv);

         Q_INIT_RESOURCE(graphlib);

         ...

         return app.exec();

     }

       同样地,若你需要显式卸载一个资源集(因插件被卸载或资源失效),需要用与前面相同的base name为参数调用Q_CLEANUP_RESOURCE() 来强制移除资源。



0 0