The imageviewer module demonstrates:
Using QGraphicsView to implement zooming & panning of a QPixmap. This works much faster for large images at high zoom levels than PyQt4\examples\widgets\imageviewer.pyw which uses a QLabel. The Qt documentation for the slower ImageViewer example is at the nokia website.
Keeping track of scroll and view transform changes so other classes can implement synchronized zooming and panning of multiple views.
Zooming by Ctrl+Mouse wheel rolling in SynchableGraphicsView.wheelEvent() (QGraphicsView already handles vertical scrolling by rolling the mouse wheel, and horizontal scrolling via Alt+Mouse wheel rolling)
The mdiimageviewer module demonstrates:
Synchronized zooming and panning of multiple image viewers.
Activating QtGui.QGraphicsView.ScrollHandDrag while the Space key is held down in MdiChild.keyPressEvent().
The documentation at http://doc.qt.nokia.com/latest/qwidget.html#keyReleaseEvent is a bit unclear. It means that keyReleaseEvents are normally not passed on to other classes since the default implementation is to accept() the event.
You have to override keyPressEvent and call event.ignore() to allow keyPressEvents to be seen by other classes.
Using QSignalMapper to implement a Recently Used Files list on the File menu in MDIImageViewerWindow.updateRecentFileActions().
Using QSignalMapper to call methods — specified by string — of the currently active subwindow in MDIImageViewerWindow.createMappedAction().
Using shortcutContext in MDIImageViewerWindow.createActions() to avoid QAction::eventFilter: Ambiguous shortcut overload: Ctrl+F4 messages:
self._closeAct = QtGui.QAction(
"Cl&ose", self,
shortcut=QtGui.QKeySequence.Close,
shortcutContext=QtCore.Qt.WidgetShortcut,
statusTip="Close the active window",
triggered=self._mdiArea.closeActiveSubWindow)
Activating the window system menu of MDI subwindows via Ctrl+Space (Alt+Space activates the Main Window system menu) in MDIImageViewerWindow.createActions(). A QAction is created and addAction() of QMainWindow is used rather than adding it to a QMenu (since we don’t want it to be a visible menu item).
Using the status bar to display image information for the currently active subwindow in MDIImageViewerWindow.updateStatusBar().
Using Qt resource files for menu icons.
Saving application window size & position in MDIImageViewerWindow.writeSettings().
Saving File Open dialog size, position & state (including selected filter name) in MDIImageViewerWindow.saveDialogState().
The following is done to use the more pythonic PyQt API version 2 whether or not you are using Python 2 or Python 3:
import sip
sip.setapi('QDate', 2)
sip.setapi('QTime', 2)
sip.setapi('QDateTime', 2)
sip.setapi('QUrl', 2)
sip.setapi('QTextStream', 2)
sip.setapi('QVariant', 2)
sip.setapi('QString', 2)
I use the new-style signal/slot mechanism:
self._mdiArea.subWindowActivated.connect(self.subWindowActivated)
rather than the older mechanism:
QtCore.QObject.connect(self._mdiArea, QtCore.SIGNAL("subWindowActivated()"), self, QtCore.SLOT("subWindowActivated()"))
I used pyrcc4 to convert a Qt resource collection file icons.qrc into icons_rc.py which can be imported into any python file. For example the icon exit.png can then be referenced simply by doing:
import icons_rc
...
self._exitAct = QtGui.QAction(
QtGui.QIcon(':/exit.png'),
"E&xit", self,
shortcut=QtGui.QKeySequence.Quit,
statusTip="Exit the application",
triggered=QtGui.qApp.closeAllWindows)
The following is done to allow Python 3 syntax even when running Python 2.6+:
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future_builtins import *
In theory these programs should work equally well under Python 3 but that hasn’t been tested yet.
I’ve written all the project documentation (including these web pages) using Sphinx — the source files can be found on here.
The Sphinx techniques demonstrated are:
Generating an “orphan” Home page that uses a custom sidebar.
Using the autodoc extension to generate the module documentation.
Using the inheritance diagram extension to add inheritance diagrams to the module documentation.
Using the extlinks extension to shorten references to the PyQt v4 - Python Bindings for Qt v4: Reference Guide and the Qt Class Documentation.
Creating a custom theme (based of the default theme) to have a custom footer with the Creative Commons Attribution 3.0 Licence & logo rather than a copyright notice. I also have a custom css file to style some elements differently than the defaults.
Using a global Table of Contents in the sidebar navigation panel with the current page indicated with a yellowish bullet. Most of the sites I’ve seen use the local TOC which means you have to jump back to their separate Table of Contents page to get a site overview.
Using the rst_prolog conf.py setting to create a custom role that can be used in any of the source directory’s .rst files.
Using the rst_prolog conf.py setting to create quick replacements for common Qt Class documentation links. For example, |QGraphicsView| generates the following link: QGraphicsView. These replacements even work inside Python docstrings.
You can directly use Sphinx generated pages as GitHub Pages, but as the “Using Jekyll For Complex Layouts” section explains:
“As of December 27, 2009, you can completely opt-out of Jekyll processing by creating a file named .nojekyll in the root of your pages repo and pushing that to GitHub. This should only be necessary if your site uses directories that begin with an underscore, as Jekyll sees these as special dirs and does not copy them to the final destination.”
Since Sphinx generates a number of subdirectories that start with _ in its build directory, adding .nojekyll is thus required.