Название: Перехват событий включая потомков Отправлено: blindvic от Январь 01, 2010, 16:38 Я начинающий.
Программирую для себя на питоне и кьют. Делаю сейчас свой календарь - стандартный выглядит не очень и неудобен (имхо). Сделал форму с calendarWidget и своими кнопками. (http://img233.imageshack.us/img233/7937/52267971.png) Хочу перехватить события клавы и мыши на calendarWidget, чтобы синхронно анимировать кнопки перехода по месяцам и годам. Пытаюсь использовать installEventFilter, но не получается - мой EventFilter получает события уже после того, как calendarWidget их отработал. Поигравшись, сделал вывод, что calendarWidget имеет children widget (потомок?), который получает события первым. Варанты решения, которые я вижу: 1. Узнать имя этого потомка и повесить installEventFilter прямо на него. Этот вариант мне не нравится, ибо думаю, что имплементация calendarWidget в будущем может измениться. 2. Установить installEventFilter на всех детей calendarWidget 3. И т.п. Есть ли как-нить способ попроще? Я искал в документации какой-нить метод типа installEventFilter на весь виджет и его детей. Или думал отключить виджет, и события мыши и клавы уходили на форму на к-й этот calendarWidget находится (?). Но при отключении он меняет свой цвет. Название: Re: Перехват событий включая потомков Отправлено: blindvic от Январь 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] Если cw_child1 при обработке события возвратит True, то родитель cw так и не узнает, что это событие было. Разве что cw установит фильтр событий на cw_child1.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, не зная составной ли это виджет и как его потомки обрабатывают события, чтобы перехватить события, скажем, мыши над ним ( и его потомками) ? Название: Re: Перехват событий включая потомков Отправлено: lit-uriy от Январь 01, 2010, 18:32 >>Какова техника перехвата событий виджета, если этот виджет может быть составным.
иной техники, чем установка фильтра на вложенный виджет я не видел посмотри по форуму installEventFilter + QComboBox - устанавливают на выпадающий список installEventFilter + Q***View - устанавливают на viewport Название: Re: Перехват событий включая потомков Отправлено: Dendy от Январь 01, 2010, 20:02 Если бы не одно но. QComboBox позволяет обращаться к своему view(). QAbstractItemView позволяет использовать viewport(). А QCalendarWidget полностью скрывает свою внутреннюю структуру. Если вам не нужен обработчик поверх стандартного, уже созданого контрола - можете форкнуть QCalendarWidget в какой-нибудь свой BlindvicCalendarWidget и использовать внутренние структуры как вам вздумается.
Название: Re: Перехват событий включая потомков Отправлено: blindvic от Январь 01, 2010, 20:16 Если бы не одно но. QComboBox позволяет обращаться к своему view(). QAbstractItemView позволяет использовать viewport(). А QCalendarWidget полностью скрывает свою внутреннюю структуру. Если вам не нужен обработчик поверх стандартного, уже созданого контрола - можете форкнуть QCalendarWidget в какой-нибудь свой BlindvicCalendarWidget и использовать внутренние структуры как вам вздумается. Думаю, это тоже самое, что1. Узнать имя этого потомка и повесить installEventFilter прямо на него. Этот вариант мне не нравится, ибо думаю, что имплементация calendarWidget в будущем может измениться. Спасибо за ответы.Думаю, что оптимальная технология существует, и я склоняюсь с установке installEventFilter на всех потомков. Название: Re: Перехват событий включая потомков Отправлено: blindvic от Январь 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 |