[PyQt] Suppress departure from cell in QTableView

Maurizio Berti maurizio.berti at gmail.com
Thu Feb 21 00:19:18 GMT 2019


Il giorno lun 18 feb 2019 alle ore 05:31 John F Sturtz <john at sturtz.org> ha
scritto:

> Wow!  Thank you so much for all this information.  In spite of the time I
> have spent with PyQt, it is clear I still have much to learn.  :-/
>

You'll never end to learn ;-)
I still learn things from day to day (also by replying to this mailing
list, as in this case).
While I'm still "stuck" with Python 2.7 and PyQt4 (which are *very* old)
for my most important project, I realize that there are dozens of things I
still do not know yet, even with products that old. And that's good :-)


> A much more "elegant" way to do so would be to request the actual view
> from the parent argument of createEditor(); keep in mind, though, that the
> parent of the editor is the viewport of the view (since an item view is a
> QAbstractScrollArea and its contents are in an embedded "scrollable"
> QWidget), so the reference to the view is the parent() of the parent
> argument of createEditor() method, actually.
>
> This is great!  I was looking for a way to get a reference to the view
> from the delegate, but I hadn't been able to find one.  Didn't look quite
> hard enough ...
>

That's neat, isn't it? It took me a while to understand that, since the
parent didn't seem to be a "real" and "usable" widget until I actually
realized the QAbstractScrollArea inheritance of item views, and I'm still
not quite sure that it's the best (and "programmatically correct") way to
handle this, but I think that it's a better and more coherent way to
achieve that in most cases.
Obviously, if you really know what you're doing (and, most importantly,
what you might be doing in the future), setting a "virtual" parent view
while init-ing the delegate is fine enough.

PS: in your code, you've been using model.setData() inside the
> setEditorData() method of the itemDelegate, which not only doesn't makes
> not much sense, but might also result in an infinite recursion.
>
> This is a fallout of the following peculiar fact:  My actual intention is
> to use a QLabel as the delegate editor widget, and not a QLineEdit.  I
> know that seems weird, but it gives me more precise control over the
> editing that occurs.  (Basically, I respond to keyboard input, modify the
> QLabel's text, then redisplay it.  In the attached example, I changed the
> QLineEdit back to a QLabel, so you can see what I mean).
>
[...]
>
There is one thing in the current version that still puzzles me:  In the
> most recent round of messing around, I decided to subclass QLabel, and
> then use an object of the subclass as the editor widget rather than an
> actual QLabel.  And I decided to move keypress handling from eventFilter()
> in the delegate to keyPressEvent() in the editor widget subclass.  In the
> process, it seemed to change the way Tab is handled.
>
[...]
>
The latter is the default behavior for the Tab character, I believe.  But
> the former is actually what I want.  So it works the way I'd wish when I
> handle keyboard input in the delegate.  But I'm not doing anything with Tab
> character in either case, so it seems strange to me that in one case I'm
> getting one behavior, and in the other case another.
>

I'm not quite sure I'm following you on that.
I think I can understand your "precise control" needs, but if you can
better explain what your needs are, we might help with that.
Using a QLabel for editing is not suggested, not only because it's not its
purpose, but also because it doesn't provide sufficient editing
cababilities and aidings, from both programming and UX perspectives (and
I'm usually mostly focused on the latter).
Let me explain on that.
A label doesn't show the editing cursor (you might object that for simple
editings it doesn't matter that much, but *knowing* where you're typing is
a huge feedback) and it doesn't provide any selection nor clipboard
implementation. From the user point of view that's not good, as its usage
is not intuitive: while the user can "learn" how it works from its
behavior, it's usage doesn't justify the change of behavior between similar
and common [table/editing] user interfaces.
>From a GUI programming perspective, it's also a problem whenever "common"
keyboard shortcuts come in place. If I type a valid value in the editing
cell and then use any keyboard navigation shortcut (arrows, page up/down,
home/end, and further modifier combinations) I'd expect to "move" the
editing cursor, while in you implementation it results in submitting the
value and changing focus to another cell in the view (since the value is
considered valid), according to the QKeySequence class implementation of
QKeyEvents of an item view. So, you'll need to catch *all* those cases in
the eventFilter() according to those listed in
https://doc.qt.io/archives/qt-4.8/qabstractitemview.html#details ,
including possible multiple cell selection scenarios, since you're
returning False to all "unrecognized" cases of keyboard events - thus
letting the parent object (the item view, its container layout/widget,
etc) handle those events.
That said, it might be better to keep the default QLineEdit editor. You can
then set your custom QValidator to the editor in the createEditor() or even
implement your own editor. Since it seems you're requiring numeric values
(as it looks from the regex you use in the validate() method) you can even
return a custom inherited QSpinBox, and implement its own validate(),
fixup() and/or textFromValue() methods according to your needs. I know it
might look a bit more complicated to program with, but you'll eventually
realize that it's a better solution once you understand how they behave and
how all this can actually help both you and your users.

Finally, if you are really aware about those issues, and you really want to
"escape" tab keypresses only, just add an elif key ==
QtCore.Qt.Key_Tab statement
to your eventFiler() and check for the QtCore.Qt.ShiftModifier.


In any event, I think I'm making progress.  Thanks again for the help!  I
> really appreciate it.
>

Glad to be of any help :-)

Cheers,
Maurizio

-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190221/b2db94bd/attachment.html>


More information about the PyQt mailing list