Search code examples
c++qtqt5qspinbox

Qt QSpinbox accepting '+' symbol after setting range


I have a QSpinbox whose range I am setting:

QSpinBox *SpinBox = new QSpinBox;
SpinBox->setRange(0, 100);

However, I'm able to manually enter a + sign which is not reflected in my slot.

connect (SpinBox, SIGNAL (valueChanged (QString)), this,
            SLOT (onSpinBoxChanged (QString)));

I tried replacing QString with int also. But + is not reflected in the slot.

How can I restrict entering the + sign?

I have referred some Qt and StackOverflow posts/answers of disabling the line-edit in the spinbox:

I tried to make the spinbox's line-edit ReadOnly but I am unable to do so since it's a const variable.

Some answers suggest inheriting the QSpinbox class.

Is there any other approach to restrict the + sign or disabling the QSpinbox's line-edit itself?


Solution

  • A possible solution if you do not want to inherit from the QSpinBox class is to use eventFilter, in the following code I show an example:

    #include <QApplication>
    #include <QSpinBox>
    #include <QLineEdit>
    #include <QKeyEvent>
    
    class PlusRemoveHelper: public QObject{
    public:
        using QObject::QObject;
        void addWidget(QWidget *widget){
            if(widget){
                widgets.append(widget);
                widget->installEventFilter(this);
            }
        }
    public:
        bool eventFilter(QObject *watched, QEvent *event) override
        {
            if(std::find(widgets.begin(), widgets.end(), watched) != widgets.end()
                    && event->type() == QEvent::KeyPress){
                QKeyEvent *keyevent = static_cast<QKeyEvent *>(event);
                if(keyevent->text() == "+")
                    return true;
            }
            return  QObject::eventFilter(watched, event);
        }
    private:
        QWidgetList widgets;
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QSpinBox w;
        w.setRange(0, 100);
        PlusRemoveHelper helper;
        helper.addWidget(&w);
        w.show();
    
        return a.exec();
    }
    

    You can implement the same logic if you are inside a widget:

    *.h

    ...
    class QSpinBox;
    
    class SomeClass: public SuperClass
    {
    ...
    public:
        bool eventFilter(QObject *watched, QEvent *event);
    private:
        ...
        QSpinBox *SpinBox
    };
    

    *.cpp

    SomeClass::SomeClass(...):
      SuperClass(..)
    {
        SpinBox = new QSpinBox;
        SpinBox->setRange(0, 100);
        SpinBox->installEventFilter(this):
    }
    
    
    bool SomeClass::eventFilter(QObject *watched, QEvent *event){
        if(watched == SpinBox && event->type() == QEvent::KeyPress){
            QKeyEvent *keyevent = static_cast<QKeyEvent *>(event);
            if(keyevent->text() == "+")
                return true;
        }
        return  SomeClass::eventFilter(watched, event);
    }