Версия для печати темы
Форум на CrossPlatform.RU _ Qt GUI _ Нужны идеи как реализовать поведение собственного виджета
Автор: SABROG 15.4.2010, 8:52
Собственный виджет является контейнером для других виджетов. В собственном виджете нужно ловить все движения мышки, в том числе те, которые происходят над детьми. Если курсор мышки оказывается в определенной клиенсткой позиции, предположим в угле виджета, то нужно "снять" последнее изображение, которое содержит собственный виджет (grabWidget(), render() и т.п.), затем убрать/спрятать все дочерние виджеты, отрисовать в paintEvent'e сохранённое изображение. Когда курсор мышки покинет "зону интересов", то все дочерние виджеты снова показать на экране.
В итоге поведение должно выглядеть следующим образом. Двигаем указатель мышки в угол виджета, если там находится какая-нибудь кнопка-ребенок, то клик по ней не отрабатывается, вместо этого поверх ребенка (а точнее поверх скриншота) рисуется своя кнопка, нажатие по которой и обрабатывается собственным виджетом. При покидании "зоны интересов" всё возвращается обратно. Чтобы была возможность работать с дочерней кнопкой находящейся в "зоне интересов" можно выставить паузу. Но реальная цель - сделать анимацию, а не всплывающие кнопки.
Автор: igor_bogomolov 15.4.2010, 9:19
Цитата(SABROG @ 15.4.2010, 9:52)
нужно "снять" последнее изображение, которое содержит собственный виджет (grabWidget(), render() и т.п.), затем убрать/спрятать все дочерние виджеты, отрисовать в paintEvent'e сохранённое изображение. Когда курсор мышки покинет "зону интересов", то все дочерние виджеты снова показать на экране.
Можно воспользоваться QStacketWidget'ом. Т.е. сграбил виджет, отрисовал его в фоне, после чего переключаешь слой. Когда курсор мышки покинет "зону интересов", переключаешь слой обратно. Главное чтобы не было заметно разницы м/у реальным отображением и сграбленным.
Дальше ничего не понял. Не смог визуально представить, что ты хочешь получить. Можешь попроще как то разъяснить задачу, какова цель?
Автор: SABROG 15.4.2010, 9:27
Ок, попробую объяснить на примере QStackedWidget. Отводим курсор к правой стороне QStackedWidget'a, под ним рисуется стрелочка типа "Next page", нажимаем на стрелочку, происходит, предположим, эффект растворения одной страницы QStackedWidget'a в другой странице (на ту, куда переключаемся). То есть при определенных условиях нужно применять эффекты или анимацию к текущему изображению страницы (виджета), при этом эффект зависит от расположения мышки и от того где она кликает. Или другой эффект, через перетаскивание. Зажал мышку с правой стороны виджета и перетащил всё изображение справа налево таким образом, чтобы изображение "ехало" (scroll) и за ним появлялось изображение следующего виджета (страницы). То есть как в iphon'e.
Автор: igor_bogomolov 15.4.2010, 11:03
Не могу сказать чего то конкретного. Не делал пока таких вещей. Тут нужно пробовать, экспериментировать. Можно попробовать это реализовать на графической сцене, это упростит работу с анимацией и графическими эффектами.
Есть интересное http://www.youtube.com/watch?v=jjkUEipm4eA, найти бы исходнички
Автор: SABROG 15.4.2010, 11:11
Цитата(igor_bogomolov @ 15.4.2010, 12:03)
Есть интересное видео, найти бы исходнички
Это же ролик из недавнего поста в блоге, там ссылка есть: http://gitorious.org/qt-components
Но я бы не хотел прибегать к графической сцене или к QML. Наследование от QGraphicsEffect упростило бы мне задачу, но он http://bugreports.qt.nokia.com/browse/QTBUG-9826.
Автор: Litkevich Yuriy 15.4.2010, 11:39
SABROG, а что если просто наложить виджет, который будет анимацией заниматься, поверх имеющегося (т.е. просто по нужным координатам и без компоновщика)?
Автор: SABROG 15.4.2010, 12:10
Цитата(Litkevich Yuriy @ 15.4.2010, 12:39)
SABROG, а что если просто наложить виджет, который будет анимацией заниматься, поверх имеющегося (т.е. просто по нужным координатам и без компоновщика)?
Я думал об этом. По идее это должен быть "сестринский" (sibling) виджет для детей, но которому придется делать постоянно QWidget::rise()/lower(). По сути это тоже самое, что добавить дополнительный - "особый" виджет в QStackedWidget как страницу и переключаться на него в нужный момент. При этом сделать проверку, если идет попытка переключения страницы на этот "особый" виджет, то делать переключение на самую первую страницу, минуя этот виджет. Предположим я сделаю это, как тогда решить проблемы с отловом событий мыши на дочерних виджетах, которые поместит пользователь. Единственный вариант, который я знаю - в рекурсивном цикле ставить event filter на каждый виджет через installEventFilter. Как-то это не правильно, может есть мысли как это можно сделать иначе?
Автор: Litkevich Yuriy 15.4.2010, 12:14
Я никак не могу найти пример с которым я развлекался. Это переделка:
examples\dialogs\configdialog
там при переключении страниц, страницы появлялись плавно, но я сделал, чтобы виджет наложенный на страницу был прозрачен для событий мишки. Если найду, то выложу.
Автор: AD 15.4.2010, 12:15
А я на словах все не могу понять, чего хотят добиться. Можно хоть какой-то рисунок что-ли или хотя бы близкий аналог? Просто заинтересовала тема, а врубиться что хотят сделать - не могу!
Автор: SABROG 15.4.2010, 12:38
Цитата(Litkevich Yuriy @ 15.4.2010, 13:14)
чтобы виджет наложенный на страницу был прозрачен для событий мишки
Я думал про аттрибут Qt::WA_TransparentForMouseEvents. Но, что насчет клавиатуры?
Цитата(AD @ 15.4.2010, 13:15)
А я на словах все не могу понять, чего хотят добиться. Можно хоть какой-то рисунок что-ли или хотя бы близкий аналог? Просто заинтересовала тема, а врубиться что хотят сделать - не могу!
Предположим, что один цветок это одна страничка, а второй - вторая в QStackedWidget/QStackedLayout/QTabWidget
Тут какбы сдвиг одной страницы в другую заснят на середине перетаскивания мыши.
Автор: BRE 15.4.2010, 13:13
Цитата(SABROG @ 15.4.2010, 13:38)
Тут какбы сдвиг одной страницы в другую заснят на середине перетаскивания мыши.
Так может это делать через QScrollArea?
Автор: SABROG 15.4.2010, 13:38
Цитата(BRE @ 15.4.2010, 14:13)
Так может это делать через QScrollArea?
Слишком ограниченное применение. Я хочу добиться некой универсальной прослойки, которая позволит реализовать любой эффект над списком виджетов. Вот
igor_bogomolov хотел реализовать http://www.forum.crossplatform.ru/index.php?showtopic=4573 похожий на Compiz. Почему бы и нет, только не средствами графической сцены, а самому заняться отрисовкой всей анимации.
Автор: Litkevich Yuriy 15.4.2010, 14:18
Нашёл код, который был для меня исходным: http://wiki.crossplatform.ru/index.php/Fading_Effects_with_Qt_4.1
А вот свои изменения, я, похоже, не сохранил.
Автор: igor_bogomolov 15.4.2010, 14:27
Цитата(SABROG)
Я хочу добиться некой универсальной прослойки, которая позволит реализовать любой эффект над списком виджетов.
Так графическая сцена и является этой прослойкой. Всё необходимое для этого уже ест: возможность добавлять виджеты на сцену, компоновать их (layout'ы), готовые средства для различных трансформаций, анимация, различные эффекты. Другое дело, что пока есть баги. Исправят, надеюсь в ближайших релизах.
Автор: Litkevich Yuriy 15.4.2010, 14:30
Цитата(Litkevich Yuriy @ 15.4.2010, 18:18)
Нашёл код, ...
http://labs.trolltech.com/blogs/2007/08/21/fade-effects-a-blast-from-the-past/, автор этого дела писал
Автор: SABROG 15.4.2010, 15:47
Хочу такое http://zrusin.blogspot.com/2007/04/folding.html
только нигде нет исходников. Судя по всему используется QWindowSurface.
Автор: igor_bogomolov 15.4.2010, 16:01
Ух ты. Круть. Теперь я тоже хочу такое
Нужно найти способ сделать это без использования приватных классов. Иначе будут проблемы со сборкой под Linux
Тут есть ссылки на svn. К сожалению не могу проверить сейчас. Может это как раз ссылки на исходники
http://labs.trolltech.com/page/Graphics/Examples/Examples2
Автор: SABROG 15.4.2010, 16:14
Цитата(igor_bogomolov @ 15.4.2010, 17:01)
Может это как раз ссылки на исходники
Насколько я знаю этот svn не работает. Проверить сейчас нет возможности. Когда я там пытался найти давно первый пример для box2d, то его не было.
Автор: Litkevich Yuriy 15.4.2010, 16:15
SVN-хранилище у них не работает больше, переехали в Git, но в git'е нет таких каталогов
Автор: igor_bogomolov 15.4.2010, 16:22
Цитата
SVN-хранилище у них не работает больше, переехали в Git, но в git'е нет таких каталогов
Может где то в ихнем блоге поинтересоваться где можно исходнички взять?
Автор: SABROG 15.4.2010, 16:29
Цитата(igor_bogomolov @ 15.4.2010, 17:22)
Может где то в ихнем блоге поинтересоваться где можно исходнички взять?
В комментах блога Zack'a просили, он чего-то молчит с 26 марта этого года.
Автор: Litkevich Yuriy 15.4.2010, 16:40
Цитата(igor_bogomolov @ 15.4.2010, 20:22)
Может где то в ихнем блоге поинтересоваться где можно исходнички взять?
http://labs.trolltech.com/forums/topic/2000?replies=1, голосуйте/поддерживайте
Автор: Litkevich Yuriy 23.4.2010, 21:42
Хе-хе-хе. А я оказывается ещё тот куркуль.
У меня есть рабочая копия их хранилища, в состоянии 902 версии. ftp://crossplatform.ru/misc/TrLabsFromSVN.7z
Автор: SABROG 23.4.2010, 23:28
Опяньки, гуляем мужики
void Folder::updateCache()
{
//A lot faster than grabWidget because it doesn't actually
// paint the widget, just grabs its backing store
QPaintDevice *back = windowSurface()->paintDevice();
QPixmap *px = dynamic_cast<QPixmap*>(back);
if (px) {
m_foldCache = *px;
}
}
Угумс.
QWidget *w1 = new QWidget;
Ui_AppearanceConfigWidget *form1 = new Ui_AppearanceConfigWidget;
form1->setupUi(w1);
QWidget *w2 = new QWidget;
Ui_EditConfigWidget *form2 = new Ui_EditConfigWidget;
form2->setupUi(w2);
m_first->setWrapper(w1);
m_second->setWrapper(w2);
Врапперы, хмм.
Короче принцип у них такой.
- QWindowSurface используется, чтобы быстро сграбить окно.
accept- нужно точно прицеливаться в уголок, чтобы курсор мышки не попадал на пользовательский виджет. Для этого сделаны отступы.
fail- пользовательский виджет скрывается, чтобы освободить место для рисования на background'e под ними (на wrapper'e).
failОткуда растут "ноги" у двух последних решений и почему fail:
В Qt нет стандартной возможности перехватывать события дочерних виджетов (даже если они намеренно блокируют их, нужен перехват). Отсюда отступ, который дает возможность пользователю кликнуть на виджет под пользовательским виджетом в маленьком пространстве в углу.
В Qt нет стандартной возможности рисовать родительскому виджету поверх всех своих детей. Отсюда уловка с сокрытием пользовательского виджета. Они конечно могли обойти это, но код бы серьезно вырос. У меня была надежда на бажный QGraphicsEffect о котором я запостил багрепорт и только через 10 дней тролли попросили меня предоставить компилируемый проект с демонстрацией проблемы. Затем они перевели багрепорт с "Paint system" на "Graphics view", что меня еще больше расстроило. Если они зарубят на корню возможность использовать QGraphicsEffect без графической сцены, то это меня сильно расстроит.
Собственно никакой магии в демке не оказалось. Без того же QWindowSurface в ней вполне реально обойтись. По крайней мере я теперь хоть знаю, что мыслил правильно и все мои догадки подтвердились.
Автор: Litkevich Yuriy 24.4.2010, 0:25
Цитата(SABROG @ 24.4.2010, 3:28)
- нужно точно прицеливаться в уголок, чтобы курсор мышки не попадал на пользовательский виджет. Для этого сделаны отступы. fail
можно положить в угол прозрачный виджет, навёл на него мыша, "уголок бумаги" отогнулся, как сделано в некоторых типах веб рекламы
Цитата(SABROG @ 24.4.2010, 3:28)
- пользовательский виджет скрывается, чтобы освободить место для рисования на background'e под ними (на wrapper'e). fail
опять же можно рисовать на наложеном поверх {полу}прозрачном виджете
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)