How and why Qt functions can be overridden

Giuseppe Corbelli corbelligiuseppe at mesdan.it
Mon Aug 30 10:54:51 BST 2021


On 8/29/21 1:31 AM, Maurizio Berti wrote:
> Premise: while I can read and almost always understand C++, I don't 
> really know a lot about it.
> 
> Subclassing and overriding of Qt classes is almost natural to me, but I 
> still don't understand some aspects about function overriding, since I'm 
> too accustomed to the "simpler" way of python subclassing.
> 
> For instance, many widgets have an initStyleOption that cannot be 
> overridden (well, it could, but it's never called natively), while a 
> similar function can be overridden for QStyledItemDelegate.
> 
>  From my limited knowledge I can understand that I can 
> override/overwrite a function in a subclass and be sure that it's called 
> natively by Qt if it's public or virtual (like the initStyleOption of 
> QStyledItemDelegate), but this is still a very "foggy" understanding.

Override is the correct term. Also used as an identifier for virtual 
functions in C++11.
Visibility (public/protected) is not relevant in this context. AFAIK sip 
4 can be instructed to provide access to protected C++ functions so 
these are the kind of members you may override.

For each C++ class sip 4 creates a C++ subclass that will be compiled to 
be a part of the Python module. Then you can override any public or 
protected member in Python.

Let's use QToolButton as an example.
void QToolButton::initStyleOption(QStyleOptionToolButton *option) const 
is the prototype.

It is called in:
QSize QToolButton::sizeHint() const
void QToolButton::paintEvent(QPaintEvent *)
QStyle::SubControl QToolButtonPrivate::newHoverControl(const QPoint &pos)
void QToolButton::mousePressEvent(QMouseEvent *e)

and maybe in other non-overridden methods in base classes.

Given that initStyleOption is NOT virtual and you do not (or cannot) 
reimplement all the members where it is called your overridden 
implementation is useless.
It is NOT called because each call in C++ code uses the base class as 
the method is not virtual.

In other words: when QToolButton::paintEvent() is called (Qt event 
delivery, I don't know the inner working) the 
QToolButton::initStyleOption() implementation is ALWAYS called as the 
C++ code has no way to know that an overridden implementation is 
available (method is not virtual so no vtable is generated).

> For example, I can override all QItemDelegate drawing functions, except 
> for drawBackground, which is not virtual; this means that if I want to 
> implement it (because, for some reason, I don't want to use 
> QStyledItemDelegate), I need to completely port its paint method so that 
> I can finally call a possibly custom drawBackground.

You would also need to take into account every other place where 
drawBackground() is called, possibly in base classes.

> Is it possible to make it virtual? If not (as I believe it is), then why?

No it's not. Or at least not easily as you would need to modify the Qt 
system itself.

> Also, most importantly, why is it not virtual?

Absolutely no idea.

-- 
Giuseppe Corbelli


More information about the PyQt mailing list