я использую Qt 5.3.2
с Qt Creator 3.2.1
с MinGW 4.8.2
на Windows 7
, у меня есть QSpinBox
и может изменять его значение с помощью колесика мыши, только если мышь находится над QSpinBox
, Если мышь не над QSpinBox
прокрутка колесика мыши не имеет никакого эффекта, даже если QSpinBox
все еще имеет фокус. Что мне нужно сделать, чтобы иметь возможность изменять значения в QSpinBox
что фокусируется колесом мыши, даже если мышь не зависает над ним? настройка mouseTracking
в true
не имеет такого эффекта.
использование 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
рекомендуемые. Мы обнаружим wheelEvents, когда наш spinBox в фокусе, когда 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
с QWidget
с упором. Можно также добавить другие события, которые необходимо переслать.
qApp->removeEventFilter
а также qApp->installEventFilter
Единственный способ, который я нашел внутри фильтра событий, — это предотвращение вызова самого фильтра событий при прокрутке в главном окне, что вызывает переполнение стека (условие focusWidget != this
не помогает). Вероятно, есть способ предотвратить бесконечную рекурсию без переустановки фильтра событий на каждом QWheelEvent
,