Russian Qt Forum
Сентябрь 30, 2024, 18:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перехват событий включая потомков  (Прочитано 6743 раз)
blindvic
Гость
« : Январь 01, 2010, 16:38 »

Я начинающий.
Программирую для себя на питоне и кьют.
Делаю сейчас свой календарь - стандартный выглядит не очень и неудобен (имхо).
Сделал форму с calendarWidget и своими кнопками.

Хочу перехватить события клавы и мыши на calendarWidget, чтобы синхронно анимировать кнопки перехода по месяцам и годам.
Пытаюсь использовать installEventFilter, но не получается - мой EventFilter получает события уже после того, как calendarWidget их отработал. Поигравшись, сделал вывод, что calendarWidget имеет children widget (потомок?), который получает события первым.

Варанты решения, которые я вижу:
1. Узнать имя этого потомка и повесить installEventFilter прямо на него. Этот вариант мне не нравится, ибо думаю, что имплементация calendarWidget в будущем может измениться.
2. Установить installEventFilter на всех детей calendarWidget
3. И т.п.

Есть ли как-нить способ попроще? Я искал в документации какой-нить метод типа installEventFilter на весь виджет и его детей.
Или думал отключить виджет, и события мыши и клавы уходили на форму на к-й этот calendarWidget находится (?). Но при отключении он меняет свой цвет.
Записан
blindvic
Гость
« Ответ #1 : Январь 01, 2010, 16:55 »

Т.е. в более обобщенном варианте мой вопрос звучит так:
Какова техника перехвата событий виджета, если этот виджет может быть составным.
Допустим, есть составной виджет cw (compound widget), на котором расположено 2 потомка cw_child1 и cw_child2.

Насколько я понимаю, если покрутить колесико мышки над cw_child1, то cw_child1 обработает это событие в функции event и возвратит "true if the event e was recognized and processed."
Цитировать
bool QWidget::event ( QEvent * event )   [virtual protected]
Reimplemented from QObject::event().

This is the main event handler; it handles event event. You can reimplement this function in a subclass, but we recommend using one of the specialized event handlers instead.

Key press and release events are treated differently from other events. event() checks for Tab and Shift+Tab and tries to move the focus appropriately. If there is no widget to move the focus to (or the key press is not Tab or Shift+Tab), event() calls keyPressEvent().

Mouse and tablet event handling is also slightly special: only when the widget is enabled, event() will call the specialized handlers such as mousePressEvent(); otherwise it will discard the event.

This function returns true if the event was recognized, otherwise it returns false. If the recognized event was accepted (see QEvent::accepted), any further processing such as event propagation to the parent widget stops.
...
Если cw_child1 при обработке события возвратит True, то родитель cw так и не узнает, что это событие было. Разве что cw установит фильтр событий на cw_child1.

Так вот, а как установить правильно фильтр событий на cw, не зная составной ли это виджет и как его потомки обрабатывают события, чтобы перехватить события, скажем, мыши над ним ( и его потомками) ?
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #2 : Январь 01, 2010, 18:32 »

>>Какова техника перехвата событий виджета, если этот виджет может быть составным.
иной техники, чем установка фильтра на вложенный виджет я не видел посмотри по форуму
installEventFilter + QComboBox - устанавливают на выпадающий список
installEventFilter + Q***View - устанавливают на viewport
Записан

Юра.
Dendy
Гость
« Ответ #3 : Январь 01, 2010, 20:02 »

Если бы не одно но. QComboBox позволяет обращаться к своему view(). QAbstractItemView позволяет использовать viewport(). А QCalendarWidget полностью скрывает свою внутреннюю структуру. Если вам не нужен обработчик поверх стандартного, уже созданого контрола - можете форкнуть QCalendarWidget в какой-нибудь свой BlindvicCalendarWidget и использовать внутренние структуры как вам вздумается.
Записан
blindvic
Гость
« Ответ #4 : Январь 01, 2010, 20:16 »

Если бы не одно но. QComboBox позволяет обращаться к своему view(). QAbstractItemView позволяет использовать viewport(). А QCalendarWidget полностью скрывает свою внутреннюю структуру. Если вам не нужен обработчик поверх стандартного, уже созданого контрола - можете форкнуть QCalendarWidget в какой-нибудь свой BlindvicCalendarWidget и использовать внутренние структуры как вам вздумается.
Думаю, это тоже самое, что
1. Узнать имя этого потомка и повесить installEventFilter прямо на него. Этот вариант мне не нравится, ибо думаю, что имплементация calendarWidget в будущем может измениться.
Спасибо за ответы.
Думаю, что оптимальная технология существует, и я склоняюсь с установке installEventFilter на всех потомков.
Записан
blindvic
Гость
« Ответ #5 : Январь 01, 2010, 20:27 »

Вот, что нарыл (http://lists.trolltech.com/qt-interest/2003-02/thread01008-0.html):
Цитировать
I try to catch the Qt::Key_Right (right arrow key ?) in the
main Widget of my application.

I reimplemented keyPressEvent to achieve this.

Example:
void MyWidget::keyPressEvent( QKeyEvent *e )
{
QMessageBox::information( 0, "MessageBox", "Key pressed" );
}

The MessageBox comes up for many keys like all letters, alt, shift, ctrl
F1..... but not with the arrow keys, num pad
enter key,space etc.

Where is the problem?
Цитировать
There are two possible ways:
1) overload the keyPressEvent method in the child object to ignore the event

void child::keyPressEvent(QKeyEvent* ev)
{
   ev->ignore();
}

2) create an event filter in the parent and install it in the childs (see the
documentation about event filters)

bool parent::eventFilter(QObject*,QEvent* ev)
{
  // ignore other events
  if(ev->type() != QEvent::KeyPress) return false;
  // catch key press events
  // .... do what you need here ......
  return true;
}

child->installEventFilter(parent);

А в моем случае я просто поставлю Focus policy: NoFocus. Думаю, сработает

UPDATE:
http://stackoverflow.com/questions/1716916/how-can-i-capture-all-mouse-events-in-a-widget-descended-from-a-qt-widget-in-py
« Последнее редактирование: Январь 01, 2010, 20:35 от blindvic » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.108 секунд. Запросов: 23.