4

I have a PyQt4 program that I froze using cx_freeze. The problem I am having is when I make a QGraphicsPixmapItem, which it is getting its' pixmap made from a SVG file, the Item gets made no problem, but the Pixmap doesn't load so there is no image just the item in the scene. The thing that confuses me is that this only happens when I am running it on a different computer than the one that built the exe. When I run the exe on the computer that built it the program works perfectly. Even when I try to run it on a computer with all the required python components and pyqt components installed on the computer, if it isn't the computer that built it, the pixmap is not loaded from the svg file. I am not sure if this is a problem with my cx_freeze setup.py file or if I need to change something in the main code so any help or just pointing me in the right direction will be great. My feeling is that something is getting messed up when cx_freeze is building it so I will paste the contents of my setup.py file below. Also I am running on Windows using Python v3.1.

from cx_Freeze import setup, Executable

files = ['drawings\\FULL', 'drawings\\PANEL', 'data.csv', 'panelData.csv']
binIncludes = ['C:\\Python31\\Lib\\site-packages\\PyQt4\\bin\\QtSvg4.dll']
includes = ['main', 'PunchDialog', 'ArrayDialog', 'PricingDialog', 'FontAndInputDialog', 'PanelSelector', 'PyQt4', 'os', 'sys', 'ctypes', 'csv']
packages = ['drawings']
path = ['C:\\Users\\Brock\\Documents\\Programming\\PanelDesigner\\DrawingFirst', 'C:\\Python31\\Lib', 'C:\\Python31\\Lib\\site-packages', 'C:\\Python31\\DLLs']

setup(
        name = 'PanelBuilder',
        version = '1.0',
        description = 'Allows user to draw custom panel layouts.',
        author = 'Brock Seabaugh',
        options = {'build_exe': {'packages':packages, 'path':path, 'include_files':files, 'bin_includes':binIncludes, 'includes':includes}},
        executables = [Executable('PanelBuilder.py')])

PS. Here is my file hierarchy(if that helps at all):

\DrawingFirst
    Main .py file
    All .py files for all custom dialogs used
    \drawings
        some modules used
        \FULL
            A bunch of SVG files used
        \PANEL
            More SVG files used
Brock S.
  • 424
  • 2
  • 7
  • 13

3 Answers3

6

This is a nasty problem I have run into myself in the past. Let me quote http://www.py2exe.org/index.cgi/Py2exeAndPyQt: (I know you are using cx_freeze but I am sure you can adapt your script)

PyQt4 and image loading (JPG, GIF, etc)

PyQt4 uses plugins to read those image formats, so you'll need to copy the folder PyQt4\plugins\imageformats to appdir\imageformats. Like in the above cases, you can use data_files for this. This won't work with bundle_files on.

If the plugins are not reachable, then QPixmap.load/loadFromData will return False when loading an image in those formats.

testapp.py:

from PyQt4 import QtGui, QtSvg
import sys

app = QtGui.QApplication([])
wnd = QtSvg.QSvgWidget()
wnd.load("flower.svg")
wnd.show()
sys.exit(app.exec_())

setup.py:

from cx_Freeze import setup, Executable
files = ['flower.svg']
includes = ['sip', 'PyQt4.QtCore']
setup(
        name = 'Example',
        version = '1.337',
        description = 'Allows user to see what I did there.',
        author = 'something',
        options = {'build_exe': {'include_files':files, 'includes':includes}},
        executables = [Executable('testapp.py')])

I created this test app on a Windows 7 machine and copied it over to a Windows XP machine. I did not have to copy any dlls around - it worked just like that.

aukaost
  • 3,778
  • 1
  • 24
  • 26
  • Ok so this appears to the answer I am looking for, but for some reason it is still giving me the same problem.I coppied the imageformats folder over and changed the qt.conf file with my app to link to the new location of the imageformats folder and everything worked still. Just to make sure I changed the qt.conf file to link to the wrong folder and that caused the same problem as the question so this was obviously a solution to this problem, except when I moved my application to a new computer I still get the same problem so I am still missing a dependency for svg files when changing comps. – Brock S. Apr 20 '11 at 19:47
  • I'll give it a try myself and see if I can figure it out. – aukaost Apr 20 '11 at 21:24
  • Thanks for the help, one more thing to note. The program is still somehow dependent on something in the Python folder. When I change the name of my Python folder it causes the same problem. So obviously I am still linked back to my Python installation to read the SVG files, but I don't know what is causing it to link back to that folder for this one reason. Thanks again for your help so far. – Brock S. Apr 20 '11 at 22:14
  • I updated the answer with an example that worked for me. You could try it on your setup to see if this also works for you. Maybe you can write a little example program that replicates your problem? I used cx_freeze 4.2.3 if that makes any difference. – aukaost Apr 20 '11 at 22:34
  • so you just used that setup file? Did you have to copy the qt.conf file or the imageformat directory? – Brock S. Apr 21 '11 at 04:30
  • Yes, all I had were those 2 files. – aukaost Apr 21 '11 at 11:16
  • Well I got my program working. Thanks for all the help. For some reason I had to include PyQt4.QtXml also. I don't know why, but I just went in my python directory and started removing files until I broke the program and found that my program was still tethered to the QtXml module. Maybe because they were QGraphicsPixmapItems that had the SVG files in them, but anyhow they need QtXml to work too. But anyways thanks for showing me that I needed the image formats folder also I would still be stuck now if it weren't for that. Thanks. – Brock S. Apr 21 '11 at 14:49
  • In case it helps those in the future, I got this working by adding `('c:\\Python27\\Lib\\site-packages\\PyQt4\\plugins\\imageformats', 'imageformats'),` to my `include_files`, without having to modify `includes` as above. – rattray Jul 01 '13 at 04:44
3

I've added a hook to cx_freeze that includes imageformats whenever PyQt4.QtGui is included in the original code. With imageformats in the right place, even the externally stored icons work.

https://bitbucket.org/anthony_tuininga/cx_freeze/pull-request/11/added-pyqt4qtgui-load-hook-that-adds/diff

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
liborm
  • 2,634
  • 20
  • 32
  • 1
    Until that (or something like it) is merged I did this ugly hack in my setup.py: http://pastebin.ca/2303611 Maybe it helps someone else. – Strayer Jan 16 '13 at 23:12
0

For people coming here from Google: if you only use QtWebKit, you do need to copy the imageformats dir (which you find in PYTHONDIR\lib\site-packages\PyQt4\plugins) into your app dir. Specifying PyQt4.QtWebKit among the includes is not enough.

Giacomo Lacava
  • 1,784
  • 13
  • 25