【问题标题】:Make QSpinBox react to mouse wheel events when cursor is not over it当光标不在其上时,使 QSpinBox 对鼠标滚轮事件作出反应
【发布时间】:2014-09-25 14:43:08
【问题描述】:

我在Windows 7 上使用Qt 5.3.2 和Qt Creator 3.2.1 和MinGW 4.8.2。我有一个QSpinBox,只有当鼠标在QSpinBox 上时才能用鼠标滚轮更改它的值。如果鼠标不在QSpinBox 上,滚动鼠标滚轮无效,即使QSpinBox 仍然具有焦点。我需要做什么才能更改QSpinBox 中的值,即使鼠标没有悬停在鼠标滚轮上也是如此?将mouseTracking 设置为true 没有那个效果。

【问题讨论】:

  • 请查看我的编辑,我添加的代码可以满足您的需求,但不需要额外的 bool 变量。

标签: c++ qt qspinbox


【解决方案1】:

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

在本例中,当您检测到滚轮事件时,将其发送到您的旋转框。

但别忘了

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

【讨论】:

  • 如果您仅在控件获得焦点时安装事件过滤器,则可以改进您的解决方案。并在焦点丢失时卸载事件过滤器。
  • @DmitrySazonov 请问,这个控件是什么?你的意思是在QWidget::focusInEvent 中安装过滤器并在QWidget::focusOutEvent 中删除它?感谢您的关注。
  • 是的,在 spinbox 上处理焦点事件。
  • @DmitrySazonov 哦,我明白你的意思,谢谢你的提示。我需要几分钟来添加这个,谢谢。
  • 您的回答让我走上了正轨。请注意:您永远不会从您的eventFilters 中返回任何内容,从而产生有趣的效果。
【解决方案2】:

我没有在问题中提到它,但我有更多 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;
}

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

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

【讨论】:

    猜你喜欢
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多