Walletfox.com

QSpinBox with a custom step


This article presents an implementation of a QSpinbox with a custom step. This type of spinbox enables to control the size of a geometric grid. The aim is to create a spinbox that has values 1,2,4,8,16,32 etc, i.e. the next value of the spinbox is found by multiplying the previous value by a factor of 2 (in mathematics this is called a geometric series).

Subclassing QSpinBox

The solution to the problem is to subclass QSpinBox and override the method that governs the step increment, i.e. the method void stepBy(int steps). This method is called whenever the user triggers a step, i.e. it is not called explicitly.

How to override void stepBy (int steps)

The method works in the following way: If the user presses Key_Down, -1 will be passed as an argument of the method, i.e. stepBy(-1) will be called automatically. On the other hand, if the user presses Key_Up, stepBy(1) will be called.

The implementation details of stepBy (int steps)

So what we really want from the method stepBy(int steps) is the following: if '1' is passed to the method (i.e. whenever Key_Up is pressed), we multiply the current value by 2. If '-1' is passed to the method, we divide the current value by 2. In all other cases, we call the original implementation. You can see the implementation below. Notice that I use the accessor value() and modifier setValue() method to accomplish this (both methods are part of the public interface of the QSpinBox class).

void CustomSpinBox::stepBy(int steps)
{
    switch(steps) {
        case 1 :    setValue(value()*2);
                    break;
        case -1 :   setValue(value()/2);
                    break;
        default:    QSpinBox::stepBy(steps);
                    break;
    }
}

You can see the entire implementation below. Notice that except for calling the constructor, you will also have to set the range of the spinbox. This is really all you have to do. Run the code and try pressing the arrow up or down, you are going to get the geometric sequence!

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    CustomSpinBox csb;
    csb.resize(120,20);
    csb.setRange(1,256);
    csb.show();

    return app.exec();
}
class CustomSpinBox : public QSpinBox
{
    Q_OBJECT
public:
    CustomSpinBox(QWidget* parent = Q_NULLPTR);
public slots:
    void stepBy(int steps);
};
CustomSpinBox::CustomSpinBox(QWidget* parent) : QSpinBox(parent){
}

void CustomSpinBox::stepBy(int steps)
{
    switch(steps) {
        case 1 :    setValue(value()*2);
                    break;
        case -1 :   setValue(value()/2);
                    break;
        default:    QSpinBox::stepBy(steps);
                    break;
    }
}

Tagged: Qt