Qt5:从滚轮事件中滤除水平分量

时间:2017-07-08 21:47:09

标签: qt scroll event-handling mousewheel

我正在尝试过滤掉基于ProjectTreeView的窗口小部件(QTreeView)中的任何水平滚轮/触摸板滚动。我们的想法是让垂直运动通过,只通过滚动条支持水平滚动。

我试图通过ProjectTreeView::wheelEvent()事件处理程序(下面)实现这一点,但该函数以某种方式具有相反的效果。我是否忽视了某些事情(太明显)或完全做错了什么?

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);
    }
}

当我尝试通过ProjectTreeView::event(QEvent*)进行过滤时,我发现了这一点 1)我几乎没有收到任何车轮事件,至少在我试图滚动时(有些是在我释放触控板时进来) 2)进入的事件没有所需的delta信息(两个组件都是0)。

这让我想起了关于Qt4实现的关于如何通过不同的小部件实际处理事件的评论。

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以通过安装和事件过滤功能轻松完成。

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 );
}

如果您希望用户通过单击滚动条来使用滚动,则可以修改窗口小部件的焦点策略。它应该解决你的问题:

setFocusPolicy(Qt::ClickFocus);

答案 1 :(得分:0)

最后,这有效:

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);
}

关键是意识到某些事件只将方向设置为水平但没有非零增量信息。

isCocoa成员将检测我何时运行调整过的XCB QPA插件(=在XQuartz下使用Qt)。