Suppose there is a temperature sensor, when that gets disconnected from machine, class B
draws a content blocker image on the whole area of QWidget
that it owns, I can monitor sensor connect /disconnect and suppose C
's fun. OnDisconnect()
gets called, I will call B::OnDisconnect()
, B
will draw blocker image on its own QWidget
, not on the one which is owned by C
.
This has everything to do with C++'s rather inflexible method implementation inheritance when compared e.g. to the Common LISP Object System.
Since B
's obscuration is always meant to be on top of B
's contents, what you effectively need is for B
to provide an overlay that draws on top of its contents, even if paintEvent
is overriden in derived classes.
See this answer for a simple example, or another answer for an overlay with blur graphical effect.
This is fairly easy to accomplish by having B
add an optional overlay widget to itself.
Example:
class OverlayWidget; // from https://stackoverflow.com/a/19367454/1329652
class ObscureOverlay : public OverlayWidget
{
public:
ObscureOverlay(QWidget * parent = {}) : OverlayWidget{parent} {}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p{this};
p.fillRect(rect(), {Qt::black});
}
};
class A : public QWidget {
...
protected:
void paintEvent(QPaintEvent *) override { ... }
};
class B : public A {
...
ObscureOverlay m_obscure{this};
public:
B() {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() {
m_obscure.show();
...
}
};
class C : public B {
...
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
...
}
};
If you don't have the source code to B
, you can add the overlay to C
, replicating original B
's functionality when obscured. All of Qt's slots are effectively virtual, so if you pass a C
to someone expecting B
and connecting to its OnDisconnect
slot, it will be C
's slot that will get invoked.
class C : public B {
Q_OBJECT
...
ObscureOverlay m_obscure{this};
public:
explicit C(QWidget * parent = {}) : B{parent} {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() { // slots are effectively virtual
m_obscure.show();
B::OnDisconnect();
}
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
QPainter p{this};
...
}
};