PDA

View Full Version : Add a custom widget to a "stock" Qt widget e.g. QSpinBox



auser
30th March 2020, 14:51
Hello,

I want to extend a "stock" Qt widget with a custom widget.

For example I want to add a additional button to a spinbox.

To archive this i used the public accessible setLayout() function. The result is not what i epected. I want to add the button left or right of the standard QSpinBox.

See this small snippet.




#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSpinBox>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QSpinBox s;

QHBoxLayout * hbl = new QHBoxLayout();
hbl->addWidget( new QPushButton("Hello"));
s.setLayout(hbl);

s.show();

return a.exec();
}


13368

In my real code I have extended the "stock" Qt widget and therefore can also access the protected members.

Hoiw can i access the "real" layout of QSpinBox.

Is there another solution to archive my goal?

Greetings Gerd

d_stranz
30th March 2020, 18:44
You aren't "extending" QSpinBox with this code. You are taking a standard QSpinBox and messing up its UI, as your screenshot shows. Adding the horizontal layout does not move the spin box into it, it simply causes both widgets to paint on top of each other.

There are two possible solutions:

1 - Derive a new class, using QSpinBox (or QAbstractSpinBox)as a base class. You will have to reimplement much of the class, especially layout, painting, and response to mouse actions because the QSpinBox geometry will be different. I do not recommend doing this. It's way more work than you need, and you will be spending all of your time trying to debug it.

2 - Create a new widget using QWidget or maybe QFrame as a base class. In that class, add your horizontal layout, then add the button and spin box to the layout. If you want to make your new widget act like a combination of a QSpinBox and a QPushbutton, then add signals to your new class to relay the signals from the two widgets inside it. In the constructor for your new widget, connect the signals from the button and spin box to the corresponding signals in your new class. You can also add slots to your widget which pass data into the button and spin box. I would recommend this approach.

If you go for option 2, it would be a real mistake to make the spin box and button member variables public. The whole point of deriving new classes is to hide the implementation from the outside world, and you do that by mapping signals, slots, and methods from the child widgets out to the new class interface instead.

auser
31st March 2020, 14:54
Hello,

Thanks for your answer.

As far as I understand your answer it is not wanted by design to modify "stock" widgets. But why do they leave setLayout() accessible then?

For my current task i just want to add a button to a spinbox. The button will open a formula edit dialog. after editing the formula the result will be set to the spinbox. I do not want to make complex custom widgets and just want to add a simple button.

I was aware of your option 2. But a custom widget with QWidget as base does not integrate nice with designer: Usually i promote the custom widgets in designer. With QWidget as base there are no more attributes setable in designer and it is visually just a empty area.

Generally there is also a option 3: Writing a custom widget plugin. I use the mingw compiler, because of that writing custom widget plugins is also not easy. In order to write custom widget plugins I first have to compile Creator and Designer with mingw. The last time i checkd this topic i recognized that Creator and Designer is compiled with VC++ and i do not think that this has changed now.

In order to keep it easy i decided to do a custom "formula edit" button whith an setter for an spinbox pointer.

When you know another choice to create custom widgets which are usable in designer please let me know about it.

d_stranz
31st March 2020, 19:52
I was aware of your option 2. But a custom widget with QWidget as base does not integrate nice with designer: Usually i promote the custom widgets in designer. With QWidget as base there are no more attributes setable in designer and it is visually just a empty area.

Sometimes you just have to bite the bullet and write some real code to create a GUI instead of dragging and dropping. Yes, you can write a custom widget plugin for Qt Designer, but unless you are developing a library of widgets (generally for others to use), this is overkill.

If you write a custom widget, you can add it to your UI in Qt Designer, promote it, and then set the properties you want in code after the setupUi() call in the parent widget's constructor. It isn't that much more work.