0

I am using Qt 5.3.2 with Qt Creator 3.2.1 with MinGW 4.8.2 on Windows 7. I have a QSpinBox and can change its value with the mouse wheel only if the mouse is over the QSpinBox. If the mouse is not over the QSpinBox, scrolling the mouse wheel has no effect, even though the QSpinBox still has focus. What do I need to do to be able to change values in the QSpinBox that has focus with the mouse wheel even if the mouse is not hovering over it? Setting mouseTracking to true does not have that effect.

4

2 回答 2

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

在此示例中,当您检测到车轮事件时,您将其发送到您的 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);
}
于 2014-09-25T14:55:08.963 回答
1

我没有在问题中提到它,但我有更多,QSpinBox并且测试它们似乎都不是最佳的,所以我需要一个通用的消息转发器。根据切尔诺贝利的代码,我制作了自己的消息过滤器版本:

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->removeEventFilterandqApp->installEventFilter是我发现的唯一方法,它可以防止在主窗口上滚动时事件过滤器调用自身导致堆栈溢出(条件focusWidget != this无济于事)。可能有一种方法可以防止无限递归,而无需在每个QWheelEvent.

于 2014-09-26T11:45:15.617 回答