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.
2 回答
用于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);
}
我没有在问题中提到它,但我有更多,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;
}
这会将所有QWheelEvent
s 转发到QWidget
具有焦点的 。还可以添加其他需要转发的事件。
事件过滤器内部的qApp->removeEventFilter
andqApp->installEventFilter
是我发现的唯一方法,它可以防止在主窗口上滚动时事件过滤器调用自身导致堆栈溢出(条件focusWidget != this
无济于事)。可能有一种方法可以防止无限递归,而无需在每个QWheelEvent
.