Custom widget using and extending Qt's pImpl
-
Currently I'm building a custom widget that should extend a given
QWidget
class.I want to use Qt's pImpl and tried to make use of
Q_D
,Q_Q
,Q_DECLARE_PRIVATE
and other macros.Since I don't have full access to Qt's private/internal stuff, I can not do it like it's done in the Qt source. There, the
WidgetPrivate
part inherits from e.g.QPushButtonPrivate
,QSpinBoxPrivate
or whatever widget the base class is, which my class can't (or better shouldn't, I believe).The macros above expand successfully, but there is still something missing, because of no
WidgetPrivate
/QObjectPrivate
inheritance.
If I create my own, e.g.QScopedPointer<QMyClassPrivate> const d_ptr
pointer, I get warnings that I'm shadowing the originald_ptr
due to myQObject
inheritance (well, through the widget, which I want to extend).Should I suppress and ignore these warnings?
Are there any (working and good design) templates for this?
I found this one and built my widget upon this and by looking at the Qt source how it's done there, but it still doesn't feel like a clean solution (warnings etc...).
The example template also produces warnings, btw.Is there a recommended way of doing this?
Or shouldn't it be done like this at all?I feel a bit lost :-P
Any help appreciated :) -
5.15 on Windows 10.
If I remove the
d_ptr
from my class, it still compiles, the warnings go away but of course I have no pointer to my private widget data class.
But still can access usingQ_D(myClass)
andd_func()
...
which will sooner or later crash :o)While looking for some in-depth information I came across
One section says:
Inheriting d-pointers for optimization
In the above code, creating a single Label results in the memory allocation for LabelPrivate and WidgetPrivate. If we were to employ this strategy for Qt, the situation becomes quite worse for classes like QListWidget - it is 6 levels deep in the class inheritance hierarchy and it would result in upto 6 memory allocations!
This is solved by having an inheritance hierarchy for our private classes and having the class getting instantiated pass on a the d-pointer all the way up.
Notice that when inheriting d-pointers, the declaration of the private class has to be in a separate file, for example widget_p.h. It's no longer possible to declare it in the widget.cpp file.The example then shows two classes,
Label
andWidget
(not evenQWidget
), whereLabel
inherits the latter.
Same with their private classes:class LabelPrivate : public WidgetPrivate Label::Label() : Widget(*new LabelPrivate) // initialize the d-pointer with our own Private { } Label::Label(LabelPrivate &d) : Widget(d) { }
I understand the benefits, but this will never work, when you have a
QObject
-based class, because you can neither pass your ownd_ptr
"upwards" the tree, since your own private class doesn't inherit fromQWidgetPrivate
(and furtherQObjectPrivate
), so the argument is not accepted due to wrong type, nor use the existing one, right?!That's what I am asking myself the whole time... how to adapt to the
QObject
-tree to create a fully functionalQWidget
while having your own implementation, that extends some existingQWidget
-class [ * ]?You cant? Or am I missing something?!
[ * ]: And with
QWidget
I meanQSpinBox
,QPushButton
etc, not the actual plainQWidget
, but this shouldn't make any difference, as they are allQWidget
s, just one or two level(s) down the tree :-) -
You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library.
-
@Christian-Ehrlicher said in Custom widget using and extending Qt's pImpl:
You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library
So I should have my own
d_ptr
for my custom implementation, while keeping the inherited stuff untouched?
Found out there isQ_DECLARE_PRIVATE_D(myDptr, Class)
which declares thed_func()
and everything else using the first argument, you pass to that macro.
Then I have my own d-pointer, named different thand_ptr
, which doesn't collide with the inherited, originald_ptr
fromQObject
and there I'm not shadowing it anymore.
It was just about the naming?!
Is this the way? :)Will try and see how it goes... thx @Christian-Ehrlicher , @SGaist
-
@Pl45m4 said in Custom widget using and extending Qt's pImpl:
It was just about the naming?!
Is this the way? :)I would say yes.
-