Заставьте QSpinBox реагировать на события колеса мыши, когда курсор не находится над ним

я использую Qt 5.3.2 с Qt Creator 3.2.1 с MinGW 4.8.2 на Windows 7, у меня есть QSpinBox и может изменять его значение с помощью колесика мыши, только если мышь находится над QSpinBox, Если мышь не над QSpinBoxпрокрутка колесика мыши не имеет никакого эффекта, даже если QSpinBox все еще имеет фокус. Что мне нужно сделать, чтобы иметь возможность изменять значения в QSpinBox что фокусируется колесом мыши, даже если мышь не зависает над ним? настройка mouseTracking в true не имеет такого эффекта.

0

Решение

использование 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);
}
4

Другие решения

Я не упомянул об этом в вопросе, но у меня есть больше, чем один 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,

1

По вопросам рекламы [email protected]