disable wheel in QSpinBox

Viewed 1730

I have a number of spinboxes in my PySide project and I would like to change the behavior so the so user is required to click in the field to change the value and then press the enter key. I would like to disable scroll wheel behavior for the spinboxes. I have tried setting the focus policy, but it is not taking effect.

    def light_label_event(self,text,checked):
        print("this is the pressed button's label", text)

    def populate_lights(self):
        for light in self.lights:
            light_label = QtWidgets.QSpinBox()
            light_label.setFocusPolicy(QtCore.Qt.StrongFocus)
3 Answers

You have to create a custom SpinBox and overwrite the wheelEvent method:

from PySide2 import QtWidgets


class SpinBox(QtWidgets.QSpinBox):
    def wheelEvent(self, event):
        event.ignore()

if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = SpinBox()
    w.show()
    sys.exit(app.exec_())

You can also just override the mouseEvent of existing widgets. For example, if you want to ignore scroll events in a specific spinbox you can override the wheelEvent with a lambda function that does nothing:

from PyQt5 import QtWidgets

box = QtWidgets.QSpinBox()
box.wheelEvent = lambda event: None

Alternatively, you can use the findChildren function to change the event for all widgets of a certain type (QSpinBox, for example) that your main window contains, like so:

from PyQt5 import QtCore, QtWidgets

main = QtWidgets.QMainWindow()

'''add some QSpinboxes to main'''

opts = QtCore.Qt.FindChildrenRecursively
spinboxes = main.findChildren(QtWidgets.QSpinBox, options=opts)
for box in spinboxes:
    box.wheelEvent = lambda *event: None

This same principle could theoretically be applied to other widget classes and events, but I haven't tested it beyond spinboxes and wheel events.

It is also possible to implement an IgnoreWheelEvent class as EventFilter. This class has to implement eventFilter(QObject, QEvent). Then you can do spinBox.installEventFilter(IngoreWheelEvent).

I implemented that recently in C++. Because I don't want to post python code that might be wrong, here is my C++ implementation to get an idea. I already did installEventFilter in the constrcutor here, that saves me one line in the implementation.

class IgnoreWheelEventFilter : public QObject
{
    Q_OBJECT
public:
    IgnoreWheelEventFilter(QObject *parent) : QObject(parent) {parent->installEventFilter(this);}
protected:
    bool eventFilter(QObject *watched, QEvent *event) override
{
    if (event->type() == QEvent::Wheel)
    {
        // Ignore the event
        return true;
    }
    return QObject::eventFilter(watched, event);
}
};

//And later in the implementation...
IgnoreWheelEventFilter *ignoreFilter = new IgnoreWheelEventFilter(ui->spinBox);
// And if not done in the constructor:
// ui->spinBox->installEventFilter(ignoreFilter);
Related