Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: alex2013 от Август 23, 2013, 09:43



Название: QComboBox и колесико мышки
Отправлено: alex2013 от Август 23, 2013, 09:43
Всем привет.

Подскажите как сделать так, чтобы после того как я кликаю на комбобокс и он становится активным, можно было бы его значения перебирать колесиком мышки независимо от того, где именно указатель мышки находится.

Когда я писал проекты на MFC всё было просто: кликнул мышкой нужный комбобокс, он при этом подсвечивался и полностью брал на себя перехват мышки и
клавы. Значения в комбобоксе можно было перебирать или колесом мышки, причем независимо от того где находится курсор, или стрелками
клавиатуры.

А в Qt такое не проходит, комбобокс мы выбираем, он подсвечивается, перехватывает нажатия клавиатуры и события от колесика
мышки, но только в том случае, если  указатель мышки находится в границах комбобокса. Но стоит только мышку убрать с комбобокса, как
уже события от колесика не изменяют значения в комбобоксе, хотя при этом комбобокс все равно остается в фокусе (выделен синим
цветом).


Название: Re: QComboBox и колесико мышки
Отправлено: kambala от Август 23, 2013, 10:30
перехватывай глобальное событие прокрутки колеса и отсылай его комбобоксу если тот в фокусе


Название: Re: QComboBox и колесико мышки
Отправлено: alex2013 от Август 23, 2013, 11:08
перехватывай глобальное событие прокрутки колеса и отсылай его комбобоксу если тот в фокусе
Мысль ваша понятна. А как это в коде реализовать? Использовать bool eventFilter(QObject *target, QEvent *event) ?


Название: Re: QComboBox и колесико мышки
Отправлено: kambala от Август 23, 2013, 12:40
да, через фильтр событий, возможно даже придется его вешать на qApp

документация bool QCoreApplication::notify ( QObject * receiver, QEvent * event ) предлагает разные подходы:
Цитировать
There are five different ways that events can be processed; reimplementing this virtual function is just one of them. All five approaches are listed below:
1. Reimplementing paintEvent(), mousePressEvent() and so on. This is the commonest, easiest and least powerful way.
2. Reimplementing this function. This is very powerful, providing complete control; but only one subclass can be active at a time.
3. Installing an event filter on QCoreApplication::instance(). Such an event filter is able to process all events for all widgets, so it's just as powerful as reimplementing notify(); furthermore, it's possible to have more than one application-global event filter. Global event filters even see mouse events for disabled widgets. Note that application event filters are only called for objects that live in the main thread.
4. Reimplementing QObject::event() (as QWidget does). If you do this you get Tab key presses, and you get to see the events before any widget-specific event filters.
5. Installing an event filter on the object. Such an event filter gets all the events, including Tab and Shift+Tab key press events, as long as they do not change the focus widget.


Название: Re: QComboBox и колесико мышки
Отправлено: alex2013 от Август 23, 2013, 13:28
перехватывай глобальное событие прокрутки колеса и отсылай его комбобоксу если тот в фокусе

Как перехватывать событие я понял, а вот как его отослать именно определенному комбобоксу не знаю.

Код:

bool GraphPage::eventFilter(QObject *target, QEvent *event)
{
if (target == graphDraw || target == button0 || target == button1 || target == button2 || target == button3)
{
if(event->type() == QEvent::Wheel)
{
if(myCombobox->isEnabled())
{
                            .... вот тут , я так понимаю, надо что написать для отправки события на QComboBox myCombobox
}
}
}
return QWidget::eventFilter(target, event);
}



Название: Re: QComboBox и колесико мышки
Отправлено: kambala от Август 23, 2013, 18:53
попробуй qApp->sendEvent(myCombobox, event); и верни тру.

по идее на таргет достаточно одного условия: qobject_cast<QWidget *>(target)->parentWidget() == myCombobox->parentWidget().

а, и если ты хочешь, чтобы событие отсылалось когда комбобокс в фокусе, то условие должно быть myCombobox->hasFocus()


Название: Re: QComboBox и колесико мышки
Отправлено: alex2013 от Август 26, 2013, 10:19
попробуй qApp->sendEvent(myCombobox, event); и верни тру.
по идее на таргет достаточно одного условия: qobject_cast<QWidget *>(target)->parentWidget() == myCombobox->parentWidget().
а, и если ты хочешь, чтобы событие отсылалось когда комбобокс в фокусе, то условие должно быть myCombobox->hasFocus()

Спасибо, ваши советы очень помогли. Ниже привожу почти готовый код.

Код:
bool GraphPage::eventFilter(QObject *target, QEvent *event)
{
if (target == graphDraw || target == button0 || target == button1 || target == button2 || target == button3)
{
if(event->type() == QEvent::Wheel)
{
if(myCombobox->hasFocus())
{
  qApp->sendEvent(myCombobox, event);
}
}
}
return QWidget::eventFilter(target, event);
}

Единственное что я пока не понял, так это как быть с target. Сейчас у меня изначально происходит установка фильтров событий для определенных виджетов

Код:
graphDraw->installEventFilter(this);
button0->installEventFilter(this);
button1->installEventFilter(this);
button2->installEventFilter(this);
button3->installEventFilter(this);

А уже в самой функции eventFilter я делаю проверку if (target == graphDraw || target == button0 || target == button1 || target == button2 || target == button3). При такой проверке событие прокрутки передается на комбобокс только если указатель мышки находится на одном из перечисленных выше виджетов. А если указатель мышки сместить в "чистое поле", то условие уже не выполняется.

Ваш совет
по идее на таргет достаточно одного условия: qobject_cast<QWidget *>(target)->parentWidget() == myCombobox->parentWidget().
я не совсем понял. Если такое условие написать

Код:
if (qobject_cast<QWidget *>(target)->parentWidget() == myCombobox->parentWidget())
{
     if(event->type() == QEvent::Wheel)
      ....
}
,то программа при дебаге вылетает с ошибкой


Название: Re: QComboBox и колесико мышки
Отправлено: kambala от Август 26, 2013, 10:58
Цитировать
Ниже привожу почти готовый код.
а почему тру не возвращаешь при обработке события? это нужно для того, чтобы оно не пошло дальше по цепочке.
Цитировать
Единственное что я пока не понял, так это как быть с target. Сейчас у меня изначально происходит установка фильтров событий для определенных виджетов
я ж уже предлагал решение:
Цитировать
возможно даже придется его (фильтр) вешать на qApp
Цитировать
то программа при дебаге вылетает с ошибкой
подразумевалось, что в качестве упражнения читатель сам совершит проверку на нулевой указатель :)
Код
C++ (Qt)
QWidget *targetWidget = qobject_cast<QWidget *>(target);
if (targetWidget && targetWidget->parentWidget() == myCombobox->parentWidget())
...