Reputation: 408
I have a QScrollArea with QScroller::grabGesture(wgt, QScroller::LeftMouseButtonGesture);
. Inside it, I have multiple widgets. I'm trying to make it work in such a way so that people can scroll using touch gestures without worrying about accidentally focusing and changing values of the elements inside.
I am unable to achieve this with QSlider. I have even tried overloading QSlider::event
and ignoring everything in it abd the slider is still capturing the events somehow and it does not scroll.
I find it even weirder that the QDoubleSpinbox on the left does not have these issues and the drag touch event is correctly ignored until you click on the item. Both QDoubleSpinBox and QSlider have focus policy set to StrongFocus.
Can someone help me with this?
Upvotes: 2
Views: 387
Reputation: 1
It took me 2 days to solve the same problem. The root of the issue is related to this code snippet from QAbstractScrollArea:
// don't start scrolling on a QAbstractSlider
if (qobject_cast<QAbstractSlider *>(q->viewport()->childAt(startPos))) {
return false;
}
That check is done at ScrollPrepare event. The workaround is to reimplement the event handling without that check:
ui->scrollArea->installEventFilter(this);
...
bool MainDialog::eventFilter(QObject *obj, QEvent *ev)
{
if (obj == ui->scrollArea && ev->type() == QEvent::ScrollPrepare)
{
QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(ev);
QScrollBar *hBar = ui->scrollArea->horizontalScrollBar();
QScrollBar *vBar = ui->scrollArea->verticalScrollBar();
se->setViewportSize(QSizeF(ui->scrollArea->viewport()->size()));
se->setContentPosRange(QRectF(0, 0, hBar->maximum(), vBar->maximum()));
se->setContentPos(QPointF(hBar->value(), vBar->value()));
se->accept();
return true;
}
return QDialog::eventFilter(obj, ev);
}
Additionally, for my application, I disable the slider movements by touching the groove, allowing changes only by handle. That is done by subclassing QSlider and reimplementing mousePressEvent:
void ProtectedSlider::mousePressEvent(QMouseEvent *ev)
{
QStyleOptionSlider opt;
initStyleOption(&opt);
if (style()->hitTestComplexControl(QStyle::CC_Slider, &opt, ev->pos(), this) == QStyle::SC_SliderHandle) QSlider::mousePressEvent(ev);
else ev->ignore();
}
Upvotes: 0