QScrollArea 内的 QSpinBox:如何防止 Spin Box 在滚动时窃取焦点?

新手上路,请多包涵

我在 QScrollArea 中有一个带有几个 QSpinBox 对象的控件。在滚动区域中滚动时一切正常,除非鼠标恰好位于其中一个 QSpinBoxes 上。然后 QSpinBox 窃取焦点,并且滚轮事件操纵旋转框值而不是滚动滚动区域。

我不想完全禁用使用鼠标滚轮来操作 QSpinBox,但我只希望它在用户明确单击或进入 QSpinBox 时发生。有没有办法防止 QSpinBox 从 QScrollArea 窃取焦点?

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

原文由 Grant Limberg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.2k
2 个回答

尝试从旋转框中删除 Qt::WheelFocusQWidget::focusPolicy

 spin->setFocusPolicy( Qt::StrongFocus );

此外,您需要防止轮事件到达旋转框。您可以使用事件过滤器来做到这一点:

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


为了完整起见,格兰特林伯格进行了编辑,因为这让我完成了 90% 的工作:

除了上面 mmutz 所说的,我还需要做一些其他的事情。我必须创建一个 QSpinBox 的子类并实现 focusInEvent(QFocusEvent*)focusOutEvent(QFocusEvent*) 。 Basically, on a focusInEvent , I change the Focus Policy to Qt::WheelFocus and on the focusOutEvent I change it back to 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);
}

原文由 Marc Mutz - mmutz 发布,翻译遵循 CC BY-SA 3.0 许可协议

为了解决这个问题,我们需要关心以下 件事:

  1. 旋转框不能通过使用鼠标滚轮 获得焦点。这可以通过将焦点策略设置为 Qt::StrongFocus 来完成。
  2. 旋转框必须仅在它 已经具有 焦点时才接受轮事件。这可以通过在 QSpinBox 子类中重新实现 QWidget::wheelEvent 来完成。

实现此功能的 MySpinBox 类的完整代码:

 class MySpinBox : public QSpinBox {

    Q_OBJECT

public:

    MySpinBox(QWidget *parent = 0) : QSpinBox(parent) {
        setFocusPolicy(Qt::StrongFocus);
    }

protected:

    virtual void wheelEvent(QWheelEvent *event) {
        if (!hasFocus()) {
            event->ignore();
        } else {
            QSpinBox::wheelEvent(event);
        }
    }
};

而已。请注意,如果您不想创建新的 QSpinBox 子类,那么您也可以使用事件过滤器来解决这个问题。

原文由 emkey08 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题