Russian Qt Forum
Ноябрь 24, 2024, 19:42
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Пользовательский интерфейс (GUI)
>
(РЕШЕНО) QMouseEvent перестают поступать в QWidget при смене родителя
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: (РЕШЕНО) QMouseEvent перестают поступать в QWidget при смене родителя (Прочитано 7604 раз)
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
(РЕШЕНО) QMouseEvent перестают поступать в QWidget при смене родителя
«
:
Сентябрь 08, 2015, 22:35 »
Есть большой главный QWidget, на котором лежат другие QWidget, для которых большой виджет родитель. У тех, которые лежат, есть обработка события QMouseEvent, по которому эти виджеты перемещаются в координатах родителя. Всё хорошо. Но среди детей, есть такие QWidget, которые сами становятся родителями, если какой-то QWidget въехал в их прямоугольник. Назовем их "рамками". То есть, если виджет перемещался по главному, и въехал в рамку, то рамка становится его родителем. А если перемещался и выехал из неё, то родителем снова становится главный виджет. Соответственно, если в рамке есть другие виджеты, то они перемещаются вместе с рамкой. Это всё работает почти хорошо, кроме одного неприятного эффекта - как только я меняю родителя виджету, в него перестают поступать события QMouseEvent. Кнопка мши при этом не отпущена, то есть, как только виджет въезжает в рамку, он перестаёт двигаться за мшой. Если кнопку отпустить, и снова взять виджет, уже лежащий в рамке и являющийся её потомком, то он начинает получать события мши и двигается. Двигается в рамке, пока он не выйдет за её границы, и у него родитель не сменится на главный большой виджет. Тогда опять события в него перестают поступать и он замирает.
Очевидно, это происходит вот почему:
Цитировать
Note: The widget becomes invisible as part of changing its parent, even if it was previously visible. You must call show() to make the widget visible again.
То есть, так как окно виджета становится не видимо, события мши перестают в него поступать. После смены родителя я разумеется делаю show(), но
даже при том, что кнопка мши остаётся нажатой, события оно почему-то не ловит
. Хотя, казалось бы, должно. Но дальше ещё смешнее - если кнопку отпустить, то при наведении курсора на виджет, события опять начинают поступать в него (при спрятывании окна виджета триггер приема событий переключился, события запретил, а кнопка мыши осталась нажата, при отпускании кнопки триггер опять переключился, события разрешил, хотя кнопка не нажата). Чего по идее наоборот не должно быть. И чё-то нет пока идеи, как это побороть...
«
Последнее редактирование: Сентябрь 09, 2015, 16:53 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
Offline
Сообщений: 4350
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #1 :
Сентябрь 09, 2015, 06:56 »
Так может не стоит менять родителя в процессе перемещения? А делать это только в момент отпускания кнопки мыши.
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #2 :
Сентябрь 09, 2015, 09:16 »
Менять родителя на ходу - затея неудачная. Если же вот "надо - и все тут" - перекрывайте QApplcation::notify (или вешайте фильтр на QApplication) и там уже принудительно посылайте кому надо событие "мши"
.
Записан
GreatSnake
Джедай : наставник для всех
Offline
Сообщений: 2921
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #3 :
Сентябрь 09, 2015, 10:51 »
По-хорошему drag'n'drop-ом должен заниматься родительский виджет, т.е. некий менеджер, а не сам drag-объект.
Записан
Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #4 :
Сентябрь 09, 2015, 15:33 »
Цитата: GreatSnake от Сентябрь 09, 2015, 10:51
По-хорошему drag'n'drop-ом должен заниматься родительский виджет, т.е. некий менеджер, а не сам drag-объект.
Сначала так и было сделано, менеджером был "главный" виджет, по которому это всё ездит. Но получилось гораздо более громоздко и очень не удобно. Фишка в том, что каждый из виджетов, как главный, так и рамки, так и обычные виджеты - это всё
плагины
. Да ещё и динамически загружаемые...
Реализация оказалась значительно проще, когда сам перетаскиваемый объект находит, кто будет его новый родитель. Фишка-2 еще в том, что тут есть иерархия - "рамки" - это тоже виджеты, и они тоже перетаскиваются (код тот же самый, что и для других виджетов), и тоже могут быть детьми других "рамок" с неограниченным уровнем вложенности. Когда всё делается самим перетаскиваемым виджетом, общее решение получается значительно проще и компактнее - главному виджету вообще нет нужды разбираться в иерархии детей-родителей, он про неё ничего не знает. Он даже не знает, что по нему что-то перетаскивают - ему это не нужно.
Цитата: Igors от Сентябрь 09, 2015, 09:16
Если же вот "надо - и все тут" - перекрывайте QApplcation::notify (или вешайте фильтр на QApplication) и там уже принудительно посылайте кому надо событие "мши"
.
Не... Так можно было бы, если бы это было монолитное приложение. Но так как все эти получатели QMouseEvent находятся в плагинах, количество и состав которых заранее не известны, реализация была бы муторной. Поэтому:
Цитата: Old от Сентябрь 09, 2015, 06:56
Так может не стоит менять родителя в процессе перемещения? А делать это только в момент отпускания кнопки мыши.
Похоже, придётся переделать на такой вариант. Были некоторые заморочки, из-за которых менять родителя было удобнее при перетаскивании. От некоторых возможностей придётся, увы, отказаться.
«
Последнее редактирование: Сентябрь 09, 2015, 15:38 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #5 :
Сентябрь 09, 2015, 16:24 »
Не... не получается по-простому менять родителя при отпускании мыши.
Фишка в том, что виджет надо не только затаскивать внутрь рамки, но и вытаскивать из неё. А если родителем является рамка, то виджет перестает отображаться, когда выезжает из рамки. Чтобы этого не было, надо при начале перетаскивания менять родителя снова с рамки на главный виджет. Но при этом... виджет закрывается и перестаёт получать события. Замкнутый круг.
Не знаю, зачем это сделано, что виджет закрывается при смене родителя - но имхо это полный маразм. И еще баг потери связи с кнопкой мыши.
Записан
2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
Offline
Сообщений: 2921
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #6 :
Сентябрь 09, 2015, 16:34 »
Чтобы избежать всех этих заморочек задействуй QDrag.
Записан
Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #7 :
Сентябрь 09, 2015, 16:50 »
Цитата: GreatSnake от Сентябрь 09, 2015, 16:34
Чтобы избежать всех этих заморочек задействуй QDrag.
Не, это ещё более громоздко и совершенно не нужно. Там маймить надо, размаймливать, с иконками возиться... В виджетах-рамках придётся делать ловушку, на главном виджете придётся делать ловушку. Куча не нужного кода. QDrag имеет смысл, когда надо тащить драг куда-то наружу, а тут перетаскивание только в границах главного виджета. Даже ограничитель сделан, чтобы за границы нельзя было вытащить
Решение очень близко - экспериментирую с grabMouse(), один раз получилось, но это было какое-то совпадение сигналов, повторить пока не удаётся.
«
Последнее редактирование: Сентябрь 09, 2015, 17:34 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: (РЕШЕНО) QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #8 :
Сентябрь 09, 2015, 16:55 »
А вообще-то с grabMouse() после show() при смене родителя работает, надо только releaseMouse() делать в обработчике mouseReleaseEvent(QMouseEvent *event). Правда иногда почему-то при grabMouse() перепрыгивает фокус на другие приложения. Не могу уловить закономерность, это довольно редко. Возможно это дырка виндозы.
Записан
2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #9 :
Сентябрь 10, 2015, 08:36 »
Цитата: Гурман от Сентябрь 09, 2015, 16:24
Не...
Цитата: Гурман от Сентябрь 09, 2015, 16:24
Не...
Неконструктивный подход, Вы немедленно начинаете искать изъяны в предложенном решении. А поскольку Вы под впечатлением своих мыслей - найти очень легко. Поэтому дело кончается упрямым "не"
Попробуйте найти какое-то рациональное зерно. Ну например
Цитата: Гурман от Сентябрь 09, 2015, 15:33
Не... Так можно было бы, если бы это было монолитное приложение. Но так как все эти получатели QMouseEvent находятся в плагинах, количество и состав которых заранее не известны, реализация была бы муторной. Поэтому:
А Вас интересует только виджет захвативший "мшу"
Да, и если Вы все еще на Qt4, то не факт что Ваша проблема воспроизведется в пятерке. Где кстати возможен удобный перехватчик на уровне окна
Записан
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #10 :
Сентябрь 10, 2015, 12:28 »
Цитата: Igors от Сентябрь 10, 2015, 08:36
Вы немедленно начинаете искать изъяны в предложенном решении.
А вы нет? Тогда я бы вас на работу не взял... Это обязательное действие, как часть конструктивного подхода. В системном программировании вообще второй обязательный шаг - поиск изъянов в предполагаемом решении, не важно, откуда оно взялось, извне заимствовано или самостоятельно придумано. Лучше найти их раньше, чем биться головой и переделывать потом. Это не всегда получается сделать, но это делать всегда надо. Я и от подчинённых всегда этого требую.
Цитата: Igors от Сентябрь 10, 2015, 08:36
А Вас интересует только виджет захвативший "мшу"
По отношению к обработке мши - да. Если имелась в виду групповая операция над несколькими виджетами, то к обработке событий мши она никакого отношения не имеет, сделана совершенно отдельно и отлично работает. С поддержкой undo и redo.
Цитата: Igors от Сентябрь 10, 2015, 08:36
если Вы все еще на Qt4, то не факт что Ваша проблема воспроизведется в пятерке
Не факт, но в данном конкретном случае это совершенно не важно. Окно виджета также точно будет терять ввод, поскольку и в Qt 5.5 виджет также становится невидим при вызове setParent() - это
описано в документации
. Возможно только, что после show() виджет станет получать события мши без необходимости вызова grabMouse(). Но grabMouse() просто ничего не изменит (в Qt 5.5 он тоже есть). Или если изменит, его можно будет удалить. Но скорее всего, всё это будет работать точно также, как в 4.х.
А вообще вопрос исчерпан - всё уже работает, как требуется.
«
Последнее редактирование: Сентябрь 10, 2015, 12:37 от Гурман
»
Записан
2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
Offline
Сообщений: 2921
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #11 :
Сентябрь 10, 2015, 12:32 »
Цитата: Гурман от Сентябрь 10, 2015, 12:28
А вообще вопрос исчерпан - всё уже работает, как требуется.
Ну да, до тех пор пока qt-ишники не вспомнят, что забыли вызвать releaseMouse() в hide()
Записан
Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
Offline
Сообщений: 1442
Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12
Re: QMouseEvent перестают поступать в QWidget при смене родителя
«
Ответ #12 :
Сентябрь 10, 2015, 12:39 »
Цитата: GreatSnake от Сентябрь 10, 2015, 12:32
Цитата: Гурман от Сентябрь 10, 2015, 12:28
А вообще вопрос исчерпан - всё уже работает, как требуется.
Ну да, до тех пор пока qt-ишники не вспомнят, что забыли вызвать releaseMouse() в hide()
Даже если вспомнят - это ничего не изменит. Ну также точно будет виджет мшу перехватывать, и также точно будет работать.
Записан
2^7-1 == 127, задумайтесь...
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...