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

TP wingusr at gmail.com
Tue Nov 2 19:56:35 GMT 2010


On Wed, Oct 27, 2010 at 2:39 PM, Hans-Peter Jansen <hpj at urpla.net> wrote:
>
> 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..

Oh, I've already done some "proof of concept" work. I've managed to
call various Leptonica functions from Python via ctypes. I am also
able to convert Leptonica's Pix structure to a QPixmap (via a QImage).
Therefore I can, for example, deskew a document page and display it in
a Qt Window without having to write a file to disk. I'm currently at
the point where I have to make some tricky UI design decisions.

OpenCV is, I believe, more focused on Computer Vision than Leptonica.
My application will mainly be dealing with document image processing
so Leptonica is a better fit. It is also a "pedagogically-oriented
open source site" so it's website and commented C source code is
helpful when trying to learn document image processing techniques (I
haven't looked at opencv's source code so I don't know how readable it
is). Additionally, Leptonica is being used by the Tesseract OCR
project (http://code.google.com/p/tesseract-ocr/) which I also one day
hope to incorporate.

>
>> 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.
>

Good to know it works on Linux, thanks. The decision to use the
<Space> key to toggle dragging with the mouse was based on how various
paint programs (like Photoshop & Paint Shop Pro work). I figured it
would be easy to create a Pan tool, but harder to implement
<Space>-down panning. And, as it turns out, it wasn't at all obvious
that I had to override keyPressEvent in my subclass in order to be
able to override it later in a parent widget.

>> 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.
>

>From what I understand, camelCasing is somewhat controversial in
Python code (maybe less so in PyQt code since Qt uses camelCasing).

>> 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?

Since my original post I have added "complete" documentation of the
PyQt MDI Image Viewer at
http://tpgit.github.com/MDIImageViewer/index.html. It is now a pretty
full example of how one can use Sphinx to document Python programs.
The original Sphinx .rst files can be viewed at
http://github.com/tpgit/MDIImageViewer/tree/master/sphinx/.

>>
>> 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 ;-)

I spent a day or so reading the dip documentation. I think, for now,
using the entire framework is a bit too complex for my needs (the
final "Complete Example" made my head explode :P). I might, however,
use the dip.ui and dip.model stuff.

>>
>> 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.
>

Okay. Noted.

>> 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..
>

It's not the subwindows I was talking about here. It's the MAIN
application window that for some reason loses it's position and
maximized state info when the contained subwindows are tiled. That's
why this behavior is so mysterious.

>> 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).

Okay.

>
>> 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?

Googling around I see the question asked a number of times but no
definitive ansower so far.

>
>> 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.
>

I figured this one out. I was getting an "Ambiguous shortcut overload:
Ctrl+F4" message that I didn't see. Once I added:

  shortcutContext=QtCore.Qt.WidgetShortcut

to my QAction, the problem went away.

>> 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.
>

Thanks for the hint, that's what I ended up doing. I created a QAction
but instead of adding it to a QMenu I just added it to the main
window.

> Pete
> _______________________________________________
> PyQt mailing list    PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
>

Thanks for all your input. I guess my original post just scared people
away since you were the only person to respond :(

Now that I've published documentation at
http://tpgit.github.com/MDIImageViewer/index.html, maybe more people
would be inclined to look at the project at
http://github.com/tpgit/MDIImageViewer/ and comment?

I may post to the Qt mailing list since the remaining issues aren't
really PyQt specific and they might have suggestions on the overall
design.


More information about the PyQt mailing list