Tory Hoke

Essays, art, and comics of the unexpected

FOLLOW:

PyQt and py2app: Seriously I don’t know what to do with you when you’re like this

More

Most Recent Posts

Day 1: An Overview

(Experience this as a TikTok.) “Play is the work of childhood.” – Jean Piaget “or children, play is serious learning.” – Mr. Rogers Adult learning is

Read More »

OK. For some crazy reason I needed to display jpegs in my python application. I know! I am a wild woman! Somebody get me chamomile and sweatpants!

I’m going to spend a while telling you how you CAN’T get jpegs to show up. If you want you can skip this part and go down to where it says “DO NOT BE SCARED.”

No problem:

  • designing a UI in Qt Designer
  • writing the application in python
  • using Pixmaps to display images — pngs! jpegs! gifs! Whee!
  • creating an app with py2app (once you’ve got it successfully installed — and that is no mean feat. I’m looking for the link that saved me…)

Medium problem:

  • Getting the ” you might be loading two sets of Qt binaries” error to go away.

You can do this by including a blank qt.conf file in your application’s Resources folder (myApp.app/Contents/Resources). macdeployqt will make a qt.conf file for you — more on that later.

Big problem:

  • Seeing the jpegs when I run the app

WHY CAN’T I SEE MY JPEGS IN MY APPED-UP PYQT APPLICATION?

  • In Qt, jpeg support is a plugin. (Only png support is native.)
  • py2app will not link plugins libraries. No, it will not.

Some people got this to work in C :

I used the qtdeploy tool to copy the frameworks into my app and provided a path to the imageformats plugin folder. This caused deployqt to copy the plugins to my bundle as well and re-link those against the frameworks in the bundle respectively. This looked like this:

$ deployqt /path/to/myApp.app /path/to/qt/plugins/imageformats/

I had to add the following to my main.cpp to have the app load the libraries correctly:

–snip–
// Set the plugins directory correctly.
// This has to be done for bundles in OS X if they are packed using the deployqt tool.
#ifdef Q_WS_MAC
QDir dir(QApplication::applicationDirPath());
dir.cdUp();
dir.cd(“Plugins”);
QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
#endif
–/snip–

Bastian Bense is very smart and persevering and I respect him. Also his advice to use macdeployqt is good, and I believe will solve your plugins issue IF you are building a C/Qt application. Even if you are making a python app, running macdeployqt on it automatically makes your qt.conf file that will get rid of the “two Qt libraries” warning.

(macdeployqt comes with Qt 4.5, and you will probably have to build it from source. I had a coworker slip me the executable. I recommend having resourceful coworkers.)

HOW TO RUN macdeployqt:

  • Build your app normally with py2app
  • Run macdeployqt on the resulting app like this:
    macdeployqt /path/to/your/app/MacOS/mySexyApp.app

And here’s an example of macdeployqt’s output:

macdeployqt output

Your plugins will appear in the folder PlugIns (note the capital *I* in Plug*I*ns).

If you like, you add that PlugIns directory to your library path like this:


if __name__ == ‘__main__’:

app = QApplication(sys.argv)
QApplication.addLibraryPath(QApplication.applicationDirPath() + “/../PlugIns”)
form = conformUI()
form.show()
sys.exit(app.exec_())

BUT. BUT BUT BUT.

If you built your app with py2app you still won’t see your jpegs.

To the best of my understanding, macdeployqt is designed to take care of stuff you would normally use otool and install_name_tool to do. But macdeployqt, otool or install_name_tool won’t help a py2app-built app, because the app forms its library links at runtime. I really don’t know much about otool or install_name_tool. I would love to be wrong about this. If I am wrong, please tell me.

NOW.

If you are like me you are depressed and scared that your beloved application is now down a featureset.

DO NOT BE SCARED.

I HAVE MADE JPEGS WORK IN MY PY2APP-BUILT APPLICATION.

I just used a ridiculous workaround. I open the images with PIL, transform them to png-friendly string content, and give that string content to a Pixmap.

I was already using reportlabs to make some PDFs, so I already had PIL (Python Imaging Library) installed.

Note that I had to install PIL as a prerequisite to using reportlabs because most of my images are pngs. Note that the only reason most of my images are pngs is because converting jpgs to pngs was my original workaround to jpgs not showing up in my python app. HA HA HA ROFLMAO.

RECIPE FOR JPEGS SHOWING IN PYTHON APP

  • Install PIL (Python Imaging Library)
  • Add these import statements:

    from PIL import Image
    import StringIO

  • Use code like this to make a PIL Image and turn it Pixmap:

    if panelItem.getImagePath() :
    pilImage = Image.open(panelItem.getImagePath())
    stringIO = StringIO.StringIO()

    pilImage.save(stringIO, format=’png’)
    pixmapImage = QPixmap()
    pixmapImage.loadFromData(stringIO.getvalue())

    if pixmapImage:
    pixmapImage = pixmapImage.scaledToWidth(preferredWidth)
    self.setPixmap(pixmapImage)

WHEWWWWWWWW. It takes a little longer to run, but it works.

py2app finds the PIL libraries and includes them, easy-peasy.

But nothing I can find will get a py2app-built application to pick up and use those Qt plugins directories. Nothing nothing nothing. It’s almost like putting libraries in the Qt plugins directory is the precise way to keep them safe from ever ending up in an app. It is like Arkham Asylum for libraries.

THE PLUGINS ARE RUNNING THE ASYLUM.

But I’m so freakin’ excited that my jpegs are showing up that I think I might cry.

Or get some chili.

Can’t decide.

I still py2app it to make the app and run macdeployqt to add the nice qt.conf.

Share This:

Comics: Rare Words

Comics: Sneaky VFX

Comics: Pure Silliness