I have a control with several QSpinBox objects inside a QScrollArea. All works fine when scrolling in the scroll area unless the mouse happens to be over one of the QSpinBoxes. Then the QSpinBox steals focus and the wheel events manipulate the spin box value rather than scrolling the scroll area.
I don't want to completely disable using the mouse wheel to manipulate the QSpinBox, but I only want it to happen if the user explicitly clicks or tabs into the QSpinBox. Is there a way to prevent the QSpinBox from stealing the focus from the QScrollArea?
As said in a comment to an answer below, setting Qt::StrongFocus does prevent the focus rect from appearing on the control, however it still steals the mouse wheel and adjusts the value in the spin box and stops the QScrollArea from scrolling. Same with Qt::ClickFocus.
Try removing
Qt::WheelFocus
from the spinbox'QWidget::focusPolicy
:In addition, you need to prevent the wheel event from reaching the spinboxes. You can do that with an event filter:
edit from Grant Limberg for completeness as this got me 90% of the way there:
In addition to what mmutz said above, I needed to do a few other things. I had to create a subclass of QSpinBox and implement
focusInEvent(QFocusEvent*)
andfocusOutEvent(QFocusEvent*)
. Basically, on afocusInEvent
, I change the Focus Policy toQt::WheelFocus
and on thefocusOutEvent
I change it back toQt::StrongFocus
.Additionally, the eventFilter method implementation in the event filter class changes its behavior based on the current focus policy of the spinbox subclass:
Just to expand you can do this with the eventFilter instead to remove the need to derive a new QMySpinBox type class:
Just to help anyone's in need, it lacks a small detail:
With help from this post we cooked a solution for Python/PySide. If someone stumbles across this. Like we did :]
My attempt at a solution. Easy to use, no subclassing required.
First, I created a new helper class:
Then I set the focus policy of the problematic widget to
StrongFocus
, either at runtime or in Qt Designer. And then I install my event filter:ui.comboBox->installEventFilter(new MouseWheelWidgetAdjustmentGuard(ui.comboBox));
Done. The
MouseWheelWidgetAdjustmentGuard
will be deleted automatically when the parent object - the combobox - is destroyed.In order to solve this, we need to care about the two following things:
Qt::StrongFocus
.QWidget::wheelEvent
within aQSpinBox
subclass.Complete code for a
MySpinBox
class which implements this:That's it. Note that if you don't want to create a new
QSpinBox
subclass, then you can also use event filters instead to solve this.