QScrollArea里面的QSpinBox:滚动时如何防止Spin Box偷走焦点?

Gra*_*erg 21 c++ qt qspinbox qscrollarea

我在QScrollArea中有一个带有几个QSpinBox对象的控件.滚动区域滚动时,一切正常,除非鼠标碰巧超过其中一个QSpinBox.然后QSpinBox窃取焦点,轮子事件操纵旋转框值而不是滚动滚动区域.

我不想完全禁用鼠标滚轮来操纵QSpinBox,但我只想让用户明确点击或标签进入QSpinBox.有没有办法阻止QSpinBox从QScrollArea窃取焦点?

正如在下面的答案的注释中所述,设置Qt :: StrongFocus确实会阻止焦点rect出现在控件上,但它仍然会窃取鼠标滚轮并调整旋转框中的值并停止QScrollArea滚动.与Qt :: ClickFocus相同.

Mar*_*utz 16

尝试Qt::WheelFocus从旋转框中删除' QWidget::focusPolicy:

spin->setFocusPolicy( Qt::StrongFocus );
Run Code Online (Sandbox Code Playgroud)

此外,您需要防止车轮事件到达旋转框.您可以使用事件过滤器执行此操作:

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 );
}
Run Code Online (Sandbox Code Playgroud)

编辑Grant Limberg的完整性,因为这让我90%的方式:

除了mmutz上面所说的,我还需要做一些其他事情.我必须创建一个QSpinBox的子类并实现focusInEvent(QFocusEvent*)focusOutEvent(QFocusEvent*).基本上,在a上focusInEvent,我将焦点政策更改为Qt::WheelFocus并将其focusOutEvent更改为Qt::StrongFocus.

void MySpinBox::focusInEvent(QFocusEvent*)
{
     setFocusPolicy(Qt::WheelFocus);
}

void MySpinBox::focusOutEvent(QFocusEvent*)
{
     setFocusPolicy(Qt::StrongFocus);
}
Run Code Online (Sandbox Code Playgroud)

此外,事件过滤器类中的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);
}
Run Code Online (Sandbox Code Playgroud)


emk*_*y08 13

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

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

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);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

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


Vio*_*ffe 9

我尝试解决方案.易于使用,无需子类化.

首先,我创建了一个新的辅助类:

#include <QObject>

class MouseWheelWidgetAdjustmentGuard : public QObject
{
public:
    explicit MouseWheelWidgetAdjustmentGuard(QObject *parent);

protected:
    bool eventFilter(QObject* o, QEvent* e) override;
};

#include <QEvent>
#include <QWidget>

MouseWheelWidgetAdjustmentGuard::MouseWheelWidgetAdjustmentGuard(QObject *parent) : QObject(parent)
{
}

bool MouseWheelWidgetAdjustmentGuard::eventFilter(QObject *o, QEvent *e)
{
    const QWidget* widget = static_cast<QWidget*>(o);
    if (e->type() == QEvent::Wheel && widget && !widget->hasFocus())
    {
        e->ignore();
        return true;
    }

    return QObject::eventFilter(o, e);
}
Run Code Online (Sandbox Code Playgroud)

然后我将有问题的窗口小部件的焦点策略设置StrongFocus为运行时或Qt设计器.然后我安装我的事件过滤器:

ui.comboBox->installEventFilter(new MouseWheelWidgetAdjustmentGuard(ui.comboBox));

完成.该MouseWheelWidgetAdjustmentGuard组合框- -被破坏时,父对象将被自动删除.


小智 5

只是为了扩展,您可以使用 eventFilter 执行此操作,而不需要派生新的 QMySpinBox 类型类:

bool eventFilter(QObject *obj, QEvent *event)
{
    QAbstractSpinBox* spinBox = qobject_cast<QAbstractSpinBox*>(obj);
    if(spinBox)
    {
        if(event->type() == QEvent::Wheel)
        {
            if(spinBox->focusPolicy() == Qt::WheelFocus)
            {
                event->accept();
                return false;
            }
            else
            {
                event->ignore();
                return true;
            }
        }
        else if(event->type() == QEvent::FocusIn)
        {
            spinBox->setFocusPolicy(Qt::WheelFocus);
        }
        else if(event->type() == QEvent::FocusOut)
        {
            spinBox->setFocusPolicy(Qt::StrongFocus);
        }
    }
    return QObject::eventFilter(obj, event);
}
Run Code Online (Sandbox Code Playgroud)