[PySide] Centered image while maintaining aspect ratio

Sean Fisk sean at seanfisk.com
Sun Mar 31 09:36:03 CEST 2013

Hello all, 

This took me a while to figure out, so I thought I would share it with the list for others needing similar functionality.

I was working on a small program in which I wanted two panes: the left should contain a QTextEdit and a QPushButton and the right should contain an image generated from the input on the left. I wanted the image on the right to be as large as possible while maintaining the original aspect ratio. The image is an SVG generated by Graphviz (http://graphviz.org/) and pydot (https://code.google.com/p/pydot/). Here is a link to a screenshot (http://seanfisk.github.com/database-serializability-graph/screenshot.png) of how it looks.

After messing around with layouts quite a bit, I realized that the right way to do it was to render the SVG on a restricted part of the canvas. QSvgWidget, which is a thin wrapper around QSvgRenderer, renders the SVG as large as possible without aspect ratio by default. This code does the trick to keep the SVG at the default aspect ratio:
from __future__ import division from PySide import QtCore, QtGui, QtSvg class AspectRatioSvgWidget(QtSvg.QSvgWidget): def paintEvent(self, paint_event): painter = QtGui.QPainter(self) default_width, default_height = self.renderer().defaultSize().toTuple() widget_width, widget_height = self.size().toTuple() ratio_x = widget_width / default_width ratio_y = widget_height / default_height if ratio_x < ratio_y: new_width = widget_width new_height = widget_width * default_height / default_width new_left = 0 new_top = (widget_height - new_height) / 2 else: new_width = widget_height * default_width / default_height new_height = widget_height new_left = (widget_width - new_width) / 2 new_top = 0 self.renderer().render( painter, QtCore.QRectF(new_left, new_top, new_width, new_height))

The key to this was realizing the default width of the SVG (which implicitly indicates the aspect ratio) can be accessed using self.renderer().defaultSize(). Now when the window is resized the SVG is as large as possible while maintaing the ratio.
I also have code laying around for a centered bitmap (e.g., PNG) which maintains its original aspect ratio. Given the choice between SVG and PNG, though, SVG was the clear winner. Kudos to Qt and PySide for having awesome SVG support too!
The full code is available on Github (https://github.com/seanfisk/database-serializability-graph) under serial_graph/gui.py. Hope this helps someone out!


Sean Fisk

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20130331/6fad687f/attachment.html>

More information about the PySide mailing list