Reputation: 776
I am trying to filter out any horizontal wheel/touchpad scrolling in a widget (ProjectTreeView
) that is based on a QTreeView
. The idea is to let the vertical movement pass through, supporting horizontal scrolling only via the scrollbar.
I've tried to implement this via a ProjectTreeView::wheelEvent()
event handler (below), but that function somehow has the opposite effect. Am I overlooking something (too) obvious or doing something wrong altogether?
void ProjectTreeView::wheelEvent(QWheelEvent *e)
{
if ((e->pixelDelta().x() != 0 || e->angleDelta().x() !=0)
#ifdef Q_OS_MACOS
// allow horizontal scrolling controlled by a physical mouse wheel
&& e->source() != Qt::MouseEventNotSynthesized
#endif
){
QPoint pixelDelta(e->pixelDelta()), angleDelta(e->angleDelta());
// disable horizontal wheel scrolling
pixelDelta.setX(0);
angleDelta.setX(0);
// discard the original event
e->accept();
QWheelEvent filtered(e->posF(), e->globalPosF(), pixelDelta, angleDelta,
e->delta(), e->orientation(), e->buttons(),
e->modifiers(), e->phase(), e->source(), e->inverted());
QCoreApplication::sendEvent(this, &filtered);
} else {
QTreeView::wheelEvent(e);
}
}
When I try to filter via ProjectTreeView::event(QEvent*)
I observe that
1) I hardly receive any wheel events at all, at least not when I'm trying to scroll (some come in when I release the touchpad)
2) the events that do come in don't have the required delta information (both components are 0).
This reminds me of remarks I've seen about the Qt4 implementation about how the events are actually treated by a different widget.
thanks!
Upvotes: 0
Views: 1496
Reputation: 776
In the end, this works:
void ProjectTreeView::wheelEvent(QWheelEvent *e)
{
if ((e->pixelDelta().x() !=0 || e->angleDelta().x()!= 0
|| e->orientation() == Qt::Orientation::Horizontal)
#ifdef Q_OS_MACOS
// Cocoa: allow horizontal scrolling controlled by a physical mouse wheel
&& (!isCocoa || e->source() != Qt::MouseEventNotSynthesized)
#endif
){
QPoint pixelDelta(e->pixelDelta()), angleDelta(e->angleDelta());
pixelDelta.setX(0);
angleDelta.setX(0);
// discard the original event
e->ignore();
if (!pixelDelta.isNull() || !angleDelta.isNull()) {
QWheelEvent filtered(e->posF(), e->globalPosF(), pixelDelta, angleDelta,
e->delta(), Qt::Orientation::Vertical, e->buttons(),
e->modifiers(), e->phase(), Qt::MouseEventSynthesizedByApplication, e->inverted());
QCoreApplication::sendEvent(this, &filtered);
}
}
QTreeView::wheelEvent(e);
}
The key was realising that some events only had the orientation set to horizontal but no non-zero delta information.
The isCocoa
member is to detect when I'm running my tweaked XCB QPA plugin (= using Qt under XQuartz).
Upvotes: 1
Reputation: 4050
You can do it easily by installing and event filter function.
bool eventFilter( QObject * o, QEvent * e ) {
if (e->type() == QEvent::Wheel
&& qobject_cast<ProjectTreeView*>( o ) ) {
// Then do what you want, per example: ignore it.
e->ignore();
return true;
}
return QWidget::eventFilter( o, e );
}
If you want the user to use the scroll by clicking in the scrollbar then you can modify the focus polizy of the widget. It should fix your problem:
setFocusPolicy(Qt::ClickFocus);
Upvotes: 2