PDA

Просмотр полной версии : Всплывающая подсказка


Appleman
24.11.2017, 18:03
Друзья, возник ещё один вопрос. Добавляю на сцену иконку, в классе которой предусмотрен TextField для всплывающей подсказки, которая появляется рядом при наведении мыши. Проблема в том, что если поблизости имеются другие компоненты, добавленные позже, то подсказка автоматически оказывается на более низкой глубине и частично перекрывается этими компонентами. Как сделать, чтобы всегда оказывалась поверх остальных?

Godwarlock
24.11.2017, 18:33
Appleman добавь контейнер выше остальных и туда добавляй подсказку. Я бы вообще вынес подсказку в отдельный класс, ибо нечего ей делать в классе иконки

caseyryan
24.11.2017, 20:02
Друзья, возник ещё один вопрос. Добавляю на сцену иконку, в классе которой предусмотрен TextField для всплывающей подсказки, которая появляется рядом при наведении мыши. Проблема в том, что если поблизости имеются другие компоненты, добавленные позже, то подсказка автоматически оказывается на более низкой глубине и частично перекрывается этими компонентами. Как сделать, чтобы всегда оказывалась поверх остальных?

Обычно такие подсказки (которые называются туллтипы, англ. Tooltip) Делаются в отдельном контроллере, и вызываются через статические методы. А добавлять подсказку можно прямо на stage

Appleman
24.11.2017, 22:26
Appleman добавь контейнер выше остальных и туда добавляй подсказку. Я бы вообще вынес подсказку в отдельный класс, ибо нечего ей делать в классе иконки

Ну почему же нечего? Мне показалось, что очень даже удобно получилось намутить класс, подбирающий по запросу иконки: картинку, текст всплывающей подсказки на нужном языке. Хотя да, исходные объекты - из разных классов. Можно подробнее на счёт отдельного контейнера? Если я цепляю к иконке, то по определению ограничен её контейнером.

Обычно такие подсказки (которые называются туллтипы, англ. Tooltip) Делаются в отдельном контроллере, и вызываются через статические методы. А добавлять подсказку можно прямо на stage

Да, имеются в виду именно они, спасибо за правильный термин. Можно подробнее про отдельный контроллер и статические методы? Как это должно работать? У меня тоже была мысль непосредственно на stage добавлять. Но необходимость дополнительного контроллера даже близко не понимаю пока.

undefined
24.11.2017, 22:52
а как же мантра что stage приложению не принадлежит и лежать там должен только главный контейнер - root?

Wolsh
24.11.2017, 23:23
Эта страсть неистребима, засорять стейдж разными выкидышами. Вот вроде ничего не мешает иметь специальный слой поверх всего прямо в главном Вью, никаких проблем СРАЗУ разделить все отображение по слоям, чтобы HUD был всегда поверх мира, слой для главных Меню — поверх HUDа, а подсказки поверх всего (кроме, может быть, слоя с экраном для видеозаставок). Но нет, проще выплюнуть что-нибудь на стейдж.

Статический класс для подсказок хорош тем, что предоставляет один ларек для обращений, или точку входа, или как там. Правда, всем непонятным элементам придется его импортить, чтоб зарегистрироваться, но если их не катастрофически много, то почему бы и нет (а если много, то явно интерфейс требует пересмотра — игрок не должен сидеть и в задумчивости наводить мыша на каждый объект на экране, вытаясь понять что это с помощью подсказок). Если в хинте (тултипе, сорри) раскрывается дополнительная информация (не ЧТО, а ПОЧЕМУ например), то другое дело.. Но тогда надо сначала продумать механику — будет ли элемент сообщать Менеджеру подсказок только текст подсказки, или будет передавать готовый ДисплейОбжект с картинками, шкалами и графиками, который соберет сам.

А в остальном обычно делают так: элемент, который хочет рассказа о себе, регистрируется у Менеджера через статик метод register(), в который передает ссылку на себя и текст/готовый хинт, и может быть политику по размещению хинта (типа "сверху по центру, не двигать за мышкой"). Менеджер оформляет подписку на маусОвер/маусМув/маусАут для этого объекта и сохраняет текст/ДО и политику например в Dictionary. Когда с объектом случится запланированный наезд мышой, Менеджер закидывает его хинт в специальный высоколежащий слой для подсказок, а когда надо — вынимает его оттуда.

Менеджер также должен предоставить метод unregister(), который объект вызовет перед смертью в своем методе destroy().

caseyryan
25.11.2017, 15:08
Вот вроде ничего не мешает иметь специальный слой поверх всего прямо в главном Вью, никаких проблем СРАЗУ разделить все отображение по слоям, чтобы HUD был всегда поверх мира, слой для главных Меню — поверх HUDа, а подсказки поверх всего (кроме, может быть, слоя с экраном для видеозаставок). Но нет, проще выплюнуть что-нибудь на стейдж.
Слои слоями, а подсказки можно легко кидать на stage. Ничего плохого в этом нет, если у подсказки есть встроенное время жизни. У меня это обычно в районе 3 секунд было. После чего она сама удаляется снова в пул. Полностью автономная система. А вот такие высказывания вроде "ни в коем случае нельзя ничего кроме root добавлять на stage" мне напоминают паранойю) Если бы разработчики языка не хотели, чтобы что-то можно было добавлять на stage, то к ней просто не было бы доступа

Appleman
25.11.2017, 15:19
Эта страсть неистребима, засорять стейдж разными выкидышами. Вот вроде ничего не мешает иметь специальный слой поверх всего прямо в главном Вью, никаких проблем СРАЗУ разделить все отображение по слоям, чтобы HUD был всегда поверх мира, слой для главных Меню — поверх HUDа, а подсказки поверх всего (кроме, может быть, слоя с экраном для видеозаставок). Но нет, проще выплюнуть что-нибудь на стейдж.

Спокойно! Никто никуда ничего пока не выкидывает. :) Я потому и спрашиваю, что почуял, шняга какая-то выходит. Поясни, плиз, как размечать слои в главном вью? И как дочерние вью получат доступ к этим слоям?

Статический класс для подсказок хорош тем, что предоставляет один ларек для обращений, или точку входа, или как там. Правда, всем непонятным элементам придется его импортить, чтоб зарегистрироваться, но если их не катастрофически много, то почему бы и нет (а если много, то явно интерфейс требует пересмотра — игрок не должен сидеть и в задумчивости наводить мыша на каждый объект на экране, вытаясь понять что это с помощью подсказок).

Почему сразу пересматривать? Мне кажется, что это хорошая привычка - добавлять тултипы ко всем графическим элементам интерфейса для удобства игрока. В конце концов, там где одному видится сердце, другой увидит жопу. Дело такое.

На счёт импортить и регистрироваться, я тоже думал об этом, но пришёл к тому, что правильнее всё-таки обращаться к подобному "статическому" классу, который предоставит объект "под ключ", чем каждый раз по отдельности ломиться за иконкой в один класс, за полем для подсказки - в другой, и за текстом - в третий.

Если в хинте (тултипе, сорри) раскрывается дополнительная информация (не ЧТО, а ПОЧЕМУ например), то другое дело.. Но тогда надо сначала продумать механику — будет ли элемент сообщать Менеджеру подсказок только текст подсказки, или будет передавать готовый ДисплейОбжект с картинками, шкалами и графиками, который соберет сам.

А что меняется, если раскрывается? Разве статический класс не может реализовать дополнительную логику, связанную с ПОЧЕМУ? Например, текст тултипа иконки зависит от значения какого-то свойства. Почему нельзя передать это значение (или экземпляр класса, содержащий это значение) прямо в статический метод, и всё сделать в нём?

А в остальном обычно делают так: элемент, который хочет рассказа о себе, регистрируется у Менеджера через статик метод register(), в который передает ссылку на себя и текст/готовый хинт, и может быть политику по размещению хинта (типа "сверху по центру, не двигать за мышкой"). Менеджер оформляет подписку на маусОвер/маусМув/маусАут для этого объекта и сохраняет текст/ДО и политику например в Dictionary. Когда с объектом случится запланированный наезд мышой, Менеджер закидывает его хинт в специальный высоколежащий слой для подсказок, а когда надо — вынимает его оттуда.

Менеджер также должен предоставить метод unregister(), который объект вызовет перед смертью в своем методе destroy().

Я правильно уловил, что главная суть и предназначение этой регистрации - это добавление слушателя событий экранного объекта? Скажи, пожалуйста, если использовать Dictionary, то что уместно использовать в нём в качестве ключей? Сами экранные объекты: иконки, кнопки, шкалы и т.п.? А если они также "собираются на лету" в рантайме?

Wolsh
25.11.2017, 16:12
Поясни, плиз, как размечать слои в главном вью? создать переменные типа Спрайт, наделать экземпляров класса Спрайт, добавить их в отображение в нужном порядке и больше этот порядок не менять.
И как дочерние вью получат доступ к этим слоям?Никак. Им не надо. Главный Вью сам запихает кого надо куда надо, или даст ссылки на нужные слои их Менеджерам.
Разве статический класс не может реализовать дополнительную логикуМожет, почему нет. Только тогда придется заводить отдельные методы с "логикой" для каждого вида тултипов, а что-то мне подсказывает :) что их будет не два и не три.главная суть и предназначение этой регистрации - это добавление слушателя событийНет. Суть в том чтобы отдать в руки профессионала работу, не относящуюся к области ответственности самих объектов, вместо того чтобы учить каждый объект правильно показывать свою подсказку.
А если они также "собираются на лету" в рантайме?Эмм... ну так ВСЕ собираются на лету в рантайме.. Должен помереть — сделай анрегистр() и все, свободен удаляться.. Или я чего то не понял в вопросе? Может, ты имеешь ввиду что регистрация должна происходить при создании класса Хинт? Так нет же — при создании объектов. Сам объект, или тот кто его создает, проводит регистрацию объекта в Хинте.

undefined
25.11.2017, 16:39
Ничего плохого в этом нет, если у подсказки есть встроенное время жизни.
Ничего плохого нет ровно до тех пор,пока stage один.
Кейс:флэшка грузится внутрь контейнера и владелец контейнера добавляет оверлей поверх флэшки и тут начинают выскакивать "выкидыши" поверх оверлея и вообще всего на свете.

caseyryan
25.11.2017, 16:56
Ничего плохого нет ровно до тех пор,пока stage один.
Кейс:флэшка грузится внутрь контейнера и владелец контейнера добавляет оверлей поверх флэшки и тут начинают выскакивать "выкидыши" поверх оверлея и вообще всего на свете.

stage всегда один. Хоть десять флешек загрузи)) Ничего поверх разных оверлеев выскакивать не будет, если все сделано правильно.
У меня вообще система работает так (тут немного урезанный вариант):
1) Все объекты, у которых может быть подсказка применяют интерфейс ITooltip, в котором есть геттер / сеттер для поля hintText и localToGlobal(point:Point):Point
вот так:

public interface ITooltip {
function set hintText(value:String):void;
function get hintText():String;
function localToGlobal(point:Point):Point;
}

2) Класс Tooltip инициализируется с передачей ему stage, на которую он сразу вешает два слушателя
ROLL_OVER, ROLL_OUT
3) Дальше в обработчике ROLL_OVER проверяет что это за объект

private function onRollOver(e:MouseEvent):void {
if (e.target is ITooltip) {
showTooltip(e.target as ITooltip); // показываем подсказку
}
}
private function showTooltip(tooltip:ITooltip):void {
_currentHint = getHintFromPool(); // постоянно юзает один и тот же лейбл для подсказок. Больше не требуется
_currentHint .setText(tooltip.hintText);
var position:Point = tooltip.localToGlobal(new Point());
_currentHint x = position.x;
_currentHint .y = position.y;
// тут еще можно рассчитать положение со смещением, чтобы за границами экрана не вылезал, если близко к краю
stage.addChild(_currentHint );
}

4) В обработчике rollOut убирает подсказку

private function onRollOut(e:MouseEvent):void {
if (_currentHint) {
_currentHint.remove(); // там подсказка еще подписана на событие removedFromStage, чтобы возвращаться в пул
_currentHint = null;
}
}

5) Если rollOut не было в течение заданного времени, то она сама удалится
6) Профит

Не знаю как там у тебя что показывается поверх оверлеев. С этой системой такое в принципе невозможно.
Когда я ещё писал на флеше, эта либа у меня успешно кочевала из проекта в проект и никогда не глючила

п.с.
Разве статический класс не может реализовать дополнительную логику
В AS3 нет статических классов, есть только статические свойства и методы. Это так, к сведению ;)

undefined
25.11.2017, 17:22
stage всегда один
Это не значит что можно пихать на него все подряд.
Класс Tooltip инициализируется с передачей ему stage, на которую он сразу вешает два слушателя
Смотри владелец контейнера решил нарисовать поверх флэшки попап.Положим что у попапа нет бэкграунда,который перехватывает все маус ивенты.Твоя флэшка продолжет ловить ROLL_OVER, ROLL_OUT и лепить хинты поверх всего.
если все сделано правильно.
Правильно - это как раз когда все принадлежащие флэшке DO лежат в рамках одного контейнера, с которым можно делать все что угодно: перекрыть/сжать/повернуть/выставить альфу.А твой подход самый настоящий костыль.
Когда я ещё писал на флеше, эта либа у меня успешно кочевала из проекта в проект и никогда не глючила
Единственное о чем это говорит - ты не натыкался на кейсы где бы это не работало.

caseyryan
25.11.2017, 18:10
Это не значит что можно пихать на него все подряд.
Л - Логика :D Зачем аргументы? Нельзя и всё тут)
Смотри владелец контейнера решил нарисовать поверх флэшки попап.Положим что у попапа нет бэкграунда,который перехватывает все маус ивенты.Твоя флэшка продолжет ловить ROLL_OVER, ROLL_OUT и лепить хинты поверх всего.
А если бы у бабушки был ..., она была бы дедушкой) Давай без если бы да кабы.
А то можно сказать, а если бы владелец контейнера удалил твой контейнер, то твоя игра вообще не работала бы.

Правильно - это как раз когда все принадлежащие флэшке DO лежат в рамках одного контейнера, с которым можно делать все что угодно: перекрыть/сжать/повернуть/выставить альфу.А твой подход самый настоящий костыль.

Ты это "правильно" сам придумал?
Я бы сказал так, приложение, в котором что-то там со стороны загружается и добавляется, без учета логики родительского приложения - это и есть костыль.

undefined
25.11.2017, 18:24
Л - Логика Зачем аргументы? Нельзя и всё тут)
Я привел конкретный кейс когда твоя схема не сработает.
А если бы у бабушки был ..., она была бы дедушкой) Давай без если бы да кабы.
Т.е. ставим контейнеру ультиматум - не вздумай ничего рисовать поверх флэшки?Я уж молчу что появление хинта может быть и без mouseEvent'а(по таймеру например)

Добавлено через 7 минут
Любой кейс, где твоя схема не работает - это "если бы да кабы".Тогда, конечно,спорить не о чем

Добавлено через 16 минут
Я бы сказал так, приложение, в котором что-то там со стороны загружается и добавляется, без учета логики родительского приложения - это и есть костыль.
Ну так ты как раз и предлагаешь не учитывать что родитель имеет полное право что-то отрисовать поверх флэшки.

Добавлено через 26 минут
более того,это еще и вынуждает родителя тоже гадить на stage т.к. это единственный способ перекрыть всё)

caseyryan
25.11.2017, 19:24
Я привел конкретный кейс когда твоя схема не сработает.
Серёг, твой кейс притянут за уши и маловероятен. Можно ещё кучу подобных кейсов придумать, всё сводится лишь к кривости кода той флешки, которую ты загружаешь.
При правильном же подходе к разработке игры / приложения, тултипы будут отлично появляться там, где и должны. Они должны быть всегда поверх всех контейнеров. Не должна никакая флешка никаких попапов рисовать поверх тултипа. Он должен быть всегда сверху. Это такой негласный закон тултипов. Если ты мне приведешь какой-то вменяемый пример ситсемы или приложения, где это не так, я с удовольствием на это погляжу.
Я уж молчу что появление хинта может быть и без mouseEvent'а(по таймеру например)

Не может. Этот хинт появляется точно так же как в любой десктопной операционке. А именно при поднесении к нему курсора. И никак иначе.

Ну так ты как раз и предлагаешь не учитывать что родитель имеет полное право что-то отрисовать поверх флэшки.
Тут как бы речь идет о самостоятельном приложении, а не о каких-то обертках. Эти обертки на разных сайтах все что угодно могут поверх отрисовывать. Это в любом случае выглядит убого, что с хинтом, что без хинта
более того,это еще и вынуждает родителя тоже гадить на stage т.к. это единственный способ перекрыть всё)

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

undefined
25.11.2017, 20:01
Кость, смотри есть 2 случая:
1)Работает всегда с оговорками
2)Работает всегда без оговорок.
Давай на этом закончим пусть тс сам выбирает.
При грамотной архитектуре переделать (1) в (2) можно в одну строку.Я в свое время это сделал заменой этого

app.startApp(stage);

на это

app.startApp(root);

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

caseyryan
25.11.2017, 22:12
Кость, смотри есть 2 случая:
1)Работает всегда с оговорками
2)Работает всегда без оговорок.


Смотри, что мешает добавить в класс тултипа сеттер paused, к примеру?
Ставим его на паузу, при необходимости, и тултип не появляется пока не снимем с паузы.
Если допустить, что есть какая-то родительская флешка, в которой этот тултип может что-то там перекрывать, то она может просто временно отключить тултип. В любом случае и при твоем варианте у нее должен быть механизм отключения их, пусть даже блокировкой контейнера с тултипами, но должен быть. Так что код постановки на паузу этой системы легко можно реализовать.

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

undefined
26.11.2017, 00:38
Смотри, что мешает добавить в класс тултипа сеттер paused, к примеру?
Ставим его на паузу, при необходимости, и тултип не появляется пока не снимем с паузы.

Только вот разраб, заявляя что ради меня вы должны перекомпилировать свой контейнер чтоб что-то там поставить на паузу, рискует быть посланым.

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

Не нужен никакой механизм т.к. тултипы никогда не вылезут из главного контейнера и никому мешать не будут.

Appleman
26.11.2017, 19:20
Никак. Им не надо. Главный Вью сам запихает кого надо куда надо, или даст ссылки на нужные слои их Менеджерам.

У меня сейчас такая конструкция вышла. Поскольку создаваемая мини-игра будет в перспективе частью более крупной, то я решил сразу разделить View. Создал MainView, которая просто добавляется в главные DOC и ничего пока не делает. А затем контроллер мини-игры создаёт BattleView, помещает его в MainView и говорит "банкуй!". Там у меня уже начинается разметка экрана под мини-игру, создание компонентов и т.п. Поэтому я и спрашиваю, что не грех бы ей получить эти слои, чтобы ориентироваться, чего куда выставлять. Или я всё изначально неправильно спланировал?

Может, почему нет. Только тогда придется заводить отдельные методы с "логикой" для каждого вида тултипов, а что-то мне подсказывает :) что их будет не два и не три.

Это правда. Но что меняется в случае, если класс не "статический", а "обычный" с экземплярами? Какой от этого выигрыш?

Добавлено через 6 минут
В AS3 нет статических классов, есть только статические свойства и методы. Это так, к сведению ;)

Спасибо за пример. На счёт "статических" классов специально брал в кавычки. Понятно же о чём речь.

Wolsh
26.11.2017, 20:30
если класс не "статический", а "обычный" с экземплярами? Какой от этого выигрыш?Нууу... (я иногда теряюсь от твоих вопросов об очевидном) Экземпляры надо когда-то и где-то (кем-то) создавать, где-то хранить, и протаскивать ссылку до самого последнего элементика, нуждающегося в развернутом описании. То есть, для такого элемента в момент когда он хочет показать хинт (а это не только при наезде мышкой, не слушай Кейси — он видимо никогда не сталкивался с режимом обучения) совершенно не очевидно, какой именно экземпляр менеджера обслуживает его район, не очевидно, что он УЖЕ создан и как к нему обратиться с заданием. Мне вот совершенно непонятно, что за экземпляры и зачем они нужны; что за персональные данные они должны хранить и по-разному обрабатывать (а если нет индивидуальности, то зачем экземпляры). Мне видится, что они только добавят хаоса вместо порядка — "у семи нянек дитя без глазу" — так еще и за ними самими кто-то следить должен, создавать, расшаривать, укладывать спать.

Appleman
26.11.2017, 22:01
Wolsh, по-моему, у тебя нить обсуждения потерялась. Вот, смотри твой первый комментарий, а затем наши поочерёдные реплики.

Статический класс для подсказок хорош тем, что предоставляет один ларек для обращений, или точку входа, или как там. Правда, всем непонятным элементам придется его импортить, чтоб зарегистрироваться, но если их не катастрофически много, то почему бы и нет (а если много, то явно интерфейс требует пересмотра — игрок не должен сидеть и в задумчивости наводить мыша на каждый объект на экране, вытаясь понять что это с помощью подсказок). Если в хинте (тултипе, сорри) раскрывается дополнительная информация (не ЧТО, а ПОЧЕМУ например), то другое дело.. Но тогда надо сначала продумать механику — будет ли элемент сообщать Менеджеру подсказок только текст подсказки, или будет передавать готовый ДисплейОбжект с картинками, шкалами и графиками, который соберет сам.


Дальше я спросил, а чем в случае раскрытия "ПОЧЕМУ" нам не подойдёт всё тот же "статический" класс и что мешает добавить туда необходимую логику, на что ты ответил:

Может, почему нет. Только тогда придется заводить отдельные методы с "логикой" для каждого вида тултипов, а что-то мне подсказывает :) что их будет не два и не три.

И вот в ответ на это я и спросил, а в чём, собственно, выигрыш в отказе от "статического" класса. Я понял, что в качестве альтернативы на описанный случай ты предлагаешь использовать "обычный" класс с экземплярами. Я об этом и спросил, в чём его преимущество.

И ещё просьба на счёт вью пояснить - это мой первый вопрос был из предыдущего сообщения. Я его ещё короче сформулирую. Правильно ли создавать отдельные "главные" вью или должен быть один главный "командир", который просто в зависимости от текущей ситуации будет выводить разные дочерние компоненты?

Wolsh
26.11.2017, 23:23
Я понял, что в качестве альтернативы на описанный случай ты предлагаешь использовать "обычный" класс с экземплярами.Но я этого не делал.. На описаный случай я предлагал элементам САМИМ готовить свою подсказку, раз уж она такая нестандартная:
"Но тогда надо сначала продумать механику — будет ли элемент сообщать Менеджеру подсказок только текст подсказки, или будет передавать готовый ДисплейОбжект с картинками, шкалами и графиками, который соберет сам."

или должен быть один главный "командир"Он должен быть всегда.

Appleman
27.11.2017, 00:22
Всё, теперь понял, что имеется в виду. Вопрос снят, спасибо.

Wolsh
27.11.2017, 13:38
// разговоры про синглтон уехали в тему про синглтон (http://flasher.ru/forum/showthread.php?t=214778)