[PyQt] Advice requested on MDI Image Viewer with synchronized windows

Hans-Peter Jansen hpj at urpla.net
Wed Oct 27 22:39:37 BST 2010


Hi TP,

first of all, your app is fine, but this group tends to consume much 
smaller messages in one time. Hence nobody answered 'til now, and I 
fear, only few read it.. 

Something I'm missing personally is some real name.

On Tuesday 19 October 2010, 07:41:55 TP wrote:
> I'm trying to write my first PyQt program. I eventually plan on
> creating an open-source PyQt app that explores the use of various
> image processing operations (using the Leptonica C library
> http://www.leptonica.com as the underlying image processing engine).

Good luck. Looks like you need to wrap it before you leap. While I 
didn't dived into it too deeply, my guess is, that opencv might also be 
an interesting experimental image manipulation platform, that quite a 
few people would love to play with..

> One of my initial goals is to be able to view multiple QPixmaps while
> optionally keeping their view's pan and zoom values synchronized (so
> you can easily compare the results of the image processing
> operations).
>
> I've managed to write an MDI Image Viewer and I put what I've come up
> with so far at: http://github.com/tpgit/MDIImageViewer. I've tested
> it under Windows XP using ActiveState Python 2.6.4 and PyQt 4.7.7.

Fine here with linux, too, although I dislike your switching of hand 
dragging, but anyway.

> I'd like to make sure I am following PyQt & Python "good practices"
> before going on to create my "real" application. I'd appreciate any
> comments on the overall architecture & implementation. It could very
> well be that I should really be using dip
> (http://www.riverbankcomputing.co.uk/software/dip/intro) even though
> it's pretty new? (As far as Python style goes let me warn you that I
> use camelcase naming and prefix "private" data member names with a
> _.)

That's exactly the usual common style.

> I've used Sphinx (http://sphinx.pocoo.org/) to do general
> documentation, but haven't yet tried it for documenting python
> sources. I assume that I'll have to add to my existing docstrings to
> document parameters and return values?
>
> As far as testing goes, I not sure how one goes about testing PyQt
> GUI apps other than using them?

That's another reason to look into dip. Phil is also doing some 
testing ;-) 

> File Descriptions
> -----------------
>
> Here's a brief description of the two main python files following by
> some remaining implementation questions.
>
> imageviewer.py demonstrates:
>
> + Using QGraphicsView to implement zooming & panning of a pixmap.
> This works much faster for large images at high zoom levels than
> PyQt4\examples\widgets\imageviewer.pyw which uses a QLabel.
>
> + Keeping track of scroll & view changes so other classes can
> implement synchronized zooming and panning of multiple views.
>
> + Zooming by Ctrl+Mouse wheel rolling. (QGraphicsView already handles
> vertical scrolling by rolling mouse wheel, and horizontal scrolling
> via Alt+Mouse wheel rolling)
>
> mdiimageviewer.py demonstrates:
>
> + Synchronized zooming and panning of multiple image viewers.
>
> + Activating QtGui.QGraphicsView.ScrollHandDrag while the <Space> key
> is held down.
>
>   The documentation at
>   http://doc.qt.nokia.com/4.7/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.

We usually write test scripts to explore such issues, and let others 
participate..

> + Using QSignalMapper to implement a Recently Used Files list on the
>   File menu.
>
> + Using QSignalMapper to call methods specified by string of the
>   currently active subwindow.
>
> + Using the status bar to display image information for the currently
>   active subwindow.
>
> + Using Qt resource files for menu icons.
>
> + Saving application window size & position.
>
> + Saving File Open dialog size, position & state (including selected
>   filter name).
>
> Remaining Questions
> -------------------
>
> I had to specially check for QSettings boolean values and convert
> them manually to bool (since they are currently stored as strings
> rather than something like @Bool). Is this really necessary or the
> correct method when using QVariant API 2?

It looks, like all values come in as either QVariant wrapped QStrings 
(v1 API), or unicode. If you look into such a config file, you will 
notice, that QSettings hasn't any type attribute left behind (apart 
from those unsupported types starting with @). That's usually no 
problem in C++, where the programmer defines and requests the values' 
types explicitely (or implicitely). From a dynamically typed language, 
there's nothing, what can be done apart from explicitely converting the 
values to the necessary types. 

> For some reason, if the MDI subwindow(s) are tiled upon exit, the
> application window position & state are not correctly restored when
> the app is restarted?

The subwindows aren't restored here anyway..

> How do you make MDI subwindows with a shorter title bar that takes up
> less vertical screen space? Setting the WindowFlags to QtCore.Qt.Tool
> results in a Tool-like window but it then is no longer a MDI
> subwindow but rather floats outside of the main window.

This is not possible ATM. You have to live with what Qt provides, or 
roll your own MDI lib (which is, hmm, challenging).

> How can I specify NumPad /, NumPad *, and NumPad 5 as keyboard
> shortcuts?

You may get away with using some multimedia keyboard symbols, but I 
don't know any (portable) method to differentiate between Keypad / and 
the / key. David Boddie, do you?

> The Ctrl+F4 shortcut key doesn't work to close MDI subwindows? If you
> specify QtGui.QKeySequence.Close it shows up on the menu item and the
> menu item works but typing the shortcut does nothing. The standard
> Ctrl+W also doesn't work. (F4 works but I ended up using the
> non-standard Ctrl+Alt+F4 instead.)

That's strange. Again, a small self containing script demonstrating the 
issue is welcomed.

> How do you activate the window system menu of the MDI subwindows? On
> Microsoft Windows XP this is normally done with Ctrl+Space (Alt+Space
> activates the Main Window system menu).
>
>  (Ctrl+Space didn't activate the MDI subwindow System Menu until I
>  specifically added an action with that shortcut to my menu. It
> should really happen automatically without having to have a visible
> menu item in the main window menubar.)

Please keep in mind, that Qt is a multi platform toolkit, and as such, 
it may not always implement such system dependent details out of the 
box (and MDI is special, even for Windows). As long as you're able to 
get it to do what you want by adding a few lines of code, I would 
consider this as acceptable and you keep flexible (say, if you don't 
want some behavior in this area (similar to the window bars), it would 
be much more involved to get rid of these...

Of course, you can define shortcuts, that do not show up in some menu.

Pete


More information about the PyQt mailing list