当光标未在其上时,使QSpinBox对鼠标滚轮事件做出反应

时间:2014-09-25 14:43:09

标签: c++ qt qspinbox

我在Qt 5.3.2使用Qt Creator 3.2.1 MinGW 4.8.2 Windows 7 QSpinBox。我有一个QSpinBox,只有当鼠标位于QSpinBox之上时才能用鼠标滚轮更改其值。如果鼠标未在QSpinBox上方,则滚动鼠标滚轮无效,即使QSpinBox仍具有焦点。即使鼠标没有悬停在鼠标滚轮上,我还需要做些什么来改变使用鼠标滚轮聚焦的mouseTracking中的值?将true设置为{{1}}没有那种效果。

2 个答案:

答案 0 :(得分:4)

使用eventFilter执行此操作。将其安装在mainWindow

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
        if (obj == this && event->type() == QEvent::Wheel)
        {
            QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
            if(wheelEvent->delta() > 0)
                ui->spinBox->setValue(ui->spinBox->value() + 1);
            else
                ui->spinBox->setValue(ui->spinBox->value() - 1);
        }
}

这只是示例,因此您可以根据需要进行改进。

或者使用它:

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{

        if (obj == this && event->type() == QEvent::Wheel)
        {
            QApplication::sendEvent(ui->spinBox,event);
        }
}

在此示例中,当您检测到wheel事件时,将其发送到您的spinbox。

但别忘了

protected:
bool eventFilter(QObject *obj, QEvent *event);//in header

qApp->installEventFilter(this);//in constructor

建议DmitrySazonov。当我们的spinBox处于焦点时,我们将检测wheelEvents,当spinBox失去焦点时,我们不对车轮做出反应(其他小部件反应正常)。我们在一个eventFilter中执行此操作。为此,请提供新的bool变量。例如:

private:
bool spin;//in header

在构造函数中初始化它:

spin = false;

你的eventFilter应该是。

    bool MainWindow::eventFilter(QObject *obj, QEvent *event)
    {
        if(obj == ui->spinBox && event->type() == QEvent::FocusIn)
            spin = true;


        if(spin)
        {
            if (obj == this && event->type() == QEvent::Wheel)
            {
                QApplication::sendEvent(ui->spinBox,event);
            }
        }

        if(obj == ui->spinBox && event->type() == QEvent::FocusOut)
            spin = false;
    }

或者这样做,没有额外的变量:

if (obj == this && event->type() == QEvent::Wheel)
{
    if(ui->spinBox->hasFocus())
        QApplication::sendEvent(ui->spinBox,event);
}

答案 1 :(得分:1)

我没有在问题中提到它,但我有更多那个QSpinBox并且测试它们似乎都不是最佳的,所以我需要一个通用的消息转发器。基于Chernobyl's code我创建了自己的消息过滤器版本:

bool MainWindow::eventFilter(QObject *obj, QEvent *event){
    if (obj == this && event->type() == QEvent::Wheel)
    {
        auto focusWidget = QApplication::focusWidget();
        if (focusWidget){
            qApp->removeEventFilter(this);
            QApplication::sendEvent(focusWidget, event);
            qApp->installEventFilter(this);
            return true;
        }
    }
    return false;
}

这会将所有QWheelEvent转发到焦点的QWidget。还可以添加需要转发的其他事件。

事件过滤器中的qApp->removeEventFilterqApp->installEventFilter是我发现的唯一一种阻止事件过滤器在主窗口上滚动时调用自身导致堆栈溢出的方法(条件focusWidget != this没有帮助)。如果不在每个QWheelEvent上重新安装事件过滤器,可能有一种方法可以阻止无限递归。