keyPressEvent() with QCalendarWidget

Maurizio Berti maurizio.berti at gmail.com
Sat Nov 5 23:09:31 GMT 2022


 [ "crossposted" as John (who I hope doesn't mind) did reply privately, but
I believe that this might be useful to others]

Il giorno sab 5 nov 2022 alle ore 19:48 John F Sturtz <john at sturtz.org> ha
scritto:

> Your method of installing an event filter worked of course.  But
> continuing down the path of idle intellectual curiosity ...
>
> Now knowing that the calendar widget has an underlying QTableView, I might
> have thought I could get the same effect by reassigning the view's
> keyPressEvent() method.  Something like this:
>
> class Calendar(QCalendarWidget):
>
>     def __init__(self, parent=None):
>         super().__init__(parent)
>
>         self.setDateEditEnabled(False)
> #       self.findChild(QAbstractItemView).installEventFilter(self)
>         self.findChild(QAbstractItemView).keyPressEvent = self.key_press
>
> #   def eventFilter(self, obj, event):
> #       if (
> #           event.type() == event.KeyPress
> #           and event.key() == Qt.Key_Space
> #       ):
> #           print('space pressed!')
> #           return True
> #       return super().eventFilter(obj, event)
>
>     def key_press(self, event):
>         key = event.key()
>         mod = int(event.modifiers())
>         handled = False
>
>         print('key pressed!')
>
>         if key == Qt.Key_Space:
>             print('space pressed!')
>             handled = True
>
>         if not handled:
>             super().keyPressEvent(event)
>
> I realize that brute-force reassigning the keyPressEvent() method (as
> opposed to subclassing and re-implementing) is ugly.  And I probably
> wouldn't do it for real.  But I have done it on occasion just for purposes
> of mucking around (including just now, in another test file that I have).
> And it usually works.  I'm a little surprised that it doesn't here.
>

I cannot provide a complete explanation about the exact reason for which it
doesn't work, as my knowledge of C++ is limited to reading and
understanding what code does. Also, I don't know how exactly sip works with
overridden C++ functions.

That said, the reason is caused by the fact that the view used in
QCalendarWidget is actually a private subclass (named QCalendarView) which
on its own overrides keyPressEvent.
My understanding is that, since that class is not publicly declared, you
cannot override any of its methods, and you can only use its functions by
explicitly calling them (like installing the event filter).
It's possible that this is related to the "function reference caching" (I
don't know the exact term) that happens when you try to override a function
*after* it's been already called: if you overwrite mousePressEvent *after*
the default implementation has been called, it will not work. This is
obviously not the case, since you're overwriting it before it can be
called, but it's possible that it has a similar cause.

If Phil or anybody with enough knowledge of C++/sip would like to provide
more precise explanations about this, I'll be glad to read it.

Hope this helps.
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/20221106/4d6b1ca4/attachment.htm>


More information about the PyQt mailing list