我有一个控件,其中包含QScrollArea中的几个QSpinBox对象。除非鼠标恰好位于QSpinBox之一上,否则在滚动区域中滚动时,所有方法都可以正常工作。然后,QSpinBox抢占焦点,并且转轮事件控制旋转框的值,而不是滚动滚动区域。

我不想完全禁用使用鼠标滚轮来操纵QSpinBox,但是我只希望在用户显式单击或单击QSpinBox时发生。有没有一种方法可以防止QSpinBox窃取QScrollArea的焦点?

如对以下答案的评论中所述,设置Qt::StrongFocus确实可以防止焦点rect出现在控件上,但是它仍然会窃取鼠标滚轮并调整旋转框中的值,并阻止QScrollArea滚动。与Qt::ClickFocus相同。

最佳答案

尝试从Spinbox的 Qt::WheelFocus 中删除 QWidget::focusPolicy :

spin->setFocusPolicy( Qt::StrongFocus );

此外,您需要防止wheel事件到达Spinbox。您可以使用事件过滤器来做到这一点:
explicit Widget( QWidget * parent=0 )
    : QWidget( parent )
{
    // setup ...
    Q_FOREACH( QSpinBox * sp, findChildren<QSpinBox*>() ) {
        sp->installEventFilter( this );
        sp->setFocusPolicy( Qt::StrongFocus );
    }

}

/* reimp */ bool eventFilter( QObject * o, QEvent * e ) {
    if ( e->type() == QEvent::Wheel &&
         qobject_cast<QAbstractSpinBox*>( o ) )
    {
        e->ignore();
        return true;
    }
    return QWidget::eventFilter( o, e );
}

格兰特·林伯格(Grant Limberg)编辑,以确保完整性,因为这使我90%地实现了目标:

除了以上mmutz所说的,我还需要做其他一些事情。我必须创建QSpinBox的子类并实现focusInEvent(QFocusEvent*)focusOutEvent(QFocusEvent*)。基本上,在focusInEvent上,我将焦点策略更改为Qt::WheelFocus,在focusOutEvent上,将其更改回Qt::StrongFocus
void MySpinBox::focusInEvent(QFocusEvent*)
{
     setFocusPolicy(Qt::WheelFocus);
}

void MySpinBox::focusOutEvent(QFocusEvent*)
{
     setFocusPolicy(Qt::StrongFocus);
}

此外,事件过滤器类中的eventFilter方法实现会根据spinbox子类的当前焦点策略更改其行为:
bool eventFilter(QObject *o, QEvent *e)
{
    if(e->type() == QEvent::Wheel &&
       qobject_cast<QAbstractSpinBox*>(o))
    {
        if(qobject_cast<QAbstractSpinBox*>(o)->focusPolicy() == Qt::WheelFocus)
        {
            e->accept();
            return false;
        }
        else
        {
            e->ignore();
            return true;
        }
    }
    return QWidget::eventFilter(o, e);
}

关于c++ - QScrollArea内的QSpinBox : How to prevent Spin Box from stealing focus when scrolling?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5821802/

10-12 20:38