Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 17.04.2012, 23:33
s3dworld вне форума Посмотреть профиль Отправить личное сообщение для s3dworld Найти все сообщения от s3dworld
  № 1  
Ответить с цитированием
s3dworld

Регистрация: Apr 2010
Сообщений: 170
По умолчанию Двойное событие

Всем доброго вечера!

У меня есть базовый класс RenderWindow от которого наследуется любое GUI. Собственно поведение RenderWindow устроено так, что он обрабатывает события мыши и посылает события с типом произошедшего события мыши. Собственно вот как это устроено:

Код AS3:
package d.app.render
{
	import d.app.event.AppEvent;
	import d.app.event.appEvent.WindowAppEvent;
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
 
	public class RenderWindow extends RenderObject
	{
		public static const RW_TYPE_ROOT							:uint		= 0;
		public static const RW_TYPE_MAIN_MENU						:uint		= 1;
		public static const RW_TYPE_MAIN_MENU_BUTTON				:uint		= 2;
		public static const RW_TYPE_CONTEXT_MENU					:uint		= 3;
		public static const RW_TYPE_CONTEXT_MENU_ITEM				:uint		= 4;
		public static const RW_TYPE_TEXT_BUTTON						:uint		= 5;
 
		protected var rwType:uint=RW_TYPE_ROOT;
		protected var rwIsListener:Boolean=false;
		protected var rwIsDown:Boolean=false;
 
		public function RenderWindow(_type:uint,_name:String,_parent:RenderObject,_display:DisplayObject)
		{
			super(RO_TYPE_WINDOW,_name,_parent,_display);
			rwType=_type;
			mouseEnabled=true;
		}
 
		public final function rwGetType():uint
		{
			return rwType;
		}
 
		public function rwBegin():void
		{
		}
 
		public function rwUpdate():void
		{
		}
 
		public function rwResize():void
		{
		}
 
		public function rwEnd():void
		{
		}
 
		public override function roEnable():Boolean
		{
			if(roIsEnable) return false;
 
			roIsEnable=true;
 
			if(!rwIsListener)
			{
				addEventListener(MouseEvent.MOUSE_OUT,rwOnMouseOut);
				addEventListener(MouseEvent.MOUSE_OVER,rwOnMouseOver);
				addEventListener(MouseEvent.MOUSE_MOVE,rwOnMouseMove);
				addEventListener(MouseEvent.MOUSE_DOWN,rwOnMouseDown);
				addEventListener(MouseEvent.MOUSE_UP,rwOnMouseUp);
			}
 
			rwOnEnable();
			return true;
		}
 
		public override function roDisable():Boolean
		{
			if(!roIsEnable) return false;
 
			if(rwIsListener)
			{
				removeEventListener(MouseEvent.MOUSE_OUT,rwOnMouseOut);
				removeEventListener(MouseEvent.MOUSE_OVER,rwOnMouseOver);
				removeEventListener(MouseEvent.MOUSE_MOVE,rwOnMouseMove);
				removeEventListener(MouseEvent.MOUSE_DOWN,rwOnMouseDown);
				removeEventListener(MouseEvent.MOUSE_UP,rwOnMouseUp);
			}
 
			roIsEnable=false;
			rwOnDisable();
			return true;
		}
 
		protected function rwOnEnable():void
		{
		}
 
		protected function rwOnDisable():void
		{
		}
 
		public override function roLock():Boolean
		{
			if(roIsLock) return false;
			roIsLock=true;
 
			if(!rwIsListener)
			{
				addEventListener(MouseEvent.MOUSE_OUT,rwOnMouseOut);
				addEventListener(MouseEvent.MOUSE_OVER,rwOnMouseOver);
				addEventListener(MouseEvent.MOUSE_MOVE,rwOnMouseMove);
				addEventListener(MouseEvent.MOUSE_DOWN,rwOnMouseDown);
				addEventListener(MouseEvent.MOUSE_UP,rwOnMouseUp);
			}
 
			rwOnLock();
			return true;
		}
 
		public override function roUnlock():Boolean
		{
			if(!roIsLock) return false;
 
			if(rwIsListener)
			{
				removeEventListener(MouseEvent.MOUSE_OUT,rwOnMouseOut);
				removeEventListener(MouseEvent.MOUSE_OVER,rwOnMouseOver);
				removeEventListener(MouseEvent.MOUSE_MOVE,rwOnMouseMove);
				removeEventListener(MouseEvent.MOUSE_DOWN,rwOnMouseDown);
				removeEventListener(MouseEvent.MOUSE_UP,rwOnMouseUp);
			}
 
			roIsLock=false;
			rwOnUnlock();
			return true;
		}
 
		protected function rwOnLock():void
		{
		}
 
		protected function rwOnUnlock():void
		{
		}
 
		protected function rwOnMouseOut(_event:MouseEvent):void
		{
			rwIsDown=false;
			dispatchEvent(new WindowAppEvent(AppEvent.WINDOW_OUT,this));
			rwOnAdditionMouseOut(_event);
		}
 
		protected function rwOnMouseOver(_event:MouseEvent):void
		{
			rwIsDown=false;
			dispatchEvent(new WindowAppEvent(AppEvent.WINDOW_OVER,this));
			rwOnAdditionMouseOver(_event);
		}
 
		protected function rwOnMouseMove(_event:MouseEvent):void
		{
			dispatchEvent(new WindowAppEvent(AppEvent.WINDOW_MOVE,this));
			rwOnAdditionMouseMove(_event);
		}
 
		protected function rwOnMouseDown(_event:MouseEvent):void
		{
			rwIsDown=true;
			dispatchEvent(new WindowAppEvent(AppEvent.WINDOW_DOWN,this));
			rwOnAdditionMouseDown(_event);
		}
 
		protected function rwOnMouseUp(_event:MouseEvent):void
		{
			if(rwIsDown) dispatchEvent(new WindowAppEvent(AppEvent.WINDOW_CLICK,this));
			rwIsDown=false;
			rwOnAdditionMouseUp(_event);
		}
 
		protected function rwOnAdditionMouseOut(_event:MouseEvent):void
		{
		}
 
		protected function rwOnAdditionMouseOver(_event:MouseEvent):void
		{
		}
 
		protected function rwOnAdditionMouseMove(_event:MouseEvent):void
		{
		}
 
		protected function rwOnAdditionMouseDown(_event:MouseEvent):void
		{
		}
 
		protected function rwOnAdditionMouseUp(_event:MouseEvent):void
		{
		}
 
	}
 
}
Любой наследуемый класс может не переопределять полный список методов, а только добавочные методы. Ну и сам класс наследуется от класса RenderObject (а он предоставляет просто общую информацию и никакого поведения не несёт).

И вот я от RenderWindow наследую два класса:

1. GUIMainMenu
2. GUIMenuButton

GUIMenuButton я прикрепляю к GUIMainMenu в контейнер его. И вот в чём ошибка: когда я тыкаю мышкой на GUIMenuButton, у меня вызывается два события:

1. Событие GUIMenuButton
2. Событие GUIMainMenu

Почему так? Ведь GUIMenuButton лежит в GUIMainMenu и перекрывает его. Тогда почему два события происходят?

Старый 17.04.2012, 23:59
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 2  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
Обычное всплытие События. Вы считаете, что можете кликнуть по содержимому контейнера, не кликнув при этом по самому контейнеру?
__________________
Reality.getBounds(this);

Старый 18.04.2012, 00:01
fish_r вне форума Посмотреть профиль Отправить личное сообщение для fish_r Посетить домашнюю страницу fish_r Найти все сообщения от fish_r
  № 3  
Ответить с цитированием
fish_r
 
Аватар для fish_r

блогер
Регистрация: Jan 2011
Сообщений: 1,162
Записей в блоге: 4
Потому, видимо, что меню также рассылает событие получателем которого является кнопка, в фазе "захвата". Различить их можно по свойствам currentTarget, и eventPhase.

А в чем удобство вашего такого подхода? Зачем так вообще сделано?

Старый 18.04.2012, 00:21
s3dworld вне форума Посмотреть профиль Отправить личное сообщение для s3dworld Найти все сообщения от s3dworld
  № 4  
Ответить с цитированием
s3dworld

Регистрация: Apr 2010
Сообщений: 170
Wolsh
Цитата:
Обычное всплытие События. Вы считаете, что можете кликнуть по содержимому контейнера, не кликнув при этом по самому контейнеру?
Честно говоря, я так и считал. Странное если это не так.

fish_r
Цитата:
Потому, видимо, что меню также рассылает событие получателем которого является кнопка, в фазе "захвата". Различить их можно по свойствам currentTarget, и eventPhase.
Дело в том, что каждый RenderObject у меня хранит свойство roName, которое содержит имя объекта. У меню своё имя, у кнопки своё. И когда я получаю событие, я смотрю свойство roName того объекта, который пришёл в событии. Так вот, имена там разные: в первом случае имя кнопки, во втором случае - имя меню.

Цитата:
А в чем удобство вашего такого подхода? Зачем так вообще сделано?
Я уже по такому подхожу почти реализовал одну игру. Это удобно когда я всё наследую от одного класса, а затем объекты различаются на объекты пользовательского интерфейса (RenderWindow) и объекты карты (RenderMap).

Собственно сейчас я пытаюсь сделать главное меню. Нажимаю на кнопку и появляется контекстное меню. А когда я тыкаю в любое другое RenderWindow (то есть имя полученного в событие RenderWindow не совпадёт с именем RenderWindow меню), то я закрываю текущее контекстное меню. То есть есть меню GUIMainMenu, которое полоской простирается во всю ширину экрана. На этой полоске в самом начале (0,0) располагается кнопка меню GUIMenuButton. Как я нажимаю на кнопку, я открываю прикрёплённое за кнопкой GUIContextMenu, а как у меня происходит нажатие на любой другой RenderWindow, то я скрываю контекстное меню (правда оно не скрывается если тыкнули на кнопку, которая наоборот открывает это контекстное меню). Так вот, по сути если открыто контекстное меню и мы тыкнули на главное меню в его любой части, но там где нет кнопки открытия этого контекстного меню, мы должны закрыть меню. Так и происходит. Но когда я тыкаю на кнопку открытия этого меню, у меня приходят два события:

1. Событие GUIMenuButton - контекстное меню открывается
2. Событие GUIMainMenu - контекстное меню закрывается

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

Старый 18.04.2012, 00:39
fish_r вне форума Посмотреть профиль Отправить личное сообщение для fish_r Посетить домашнюю страницу fish_r Найти все сообщения от fish_r
  № 5  
Ответить с цитированием
fish_r
 
Аватар для fish_r

блогер
Регистрация: Jan 2011
Сообщений: 1,162
Записей в блоге: 4
Вот в том то и дело, что Меню рассылает событие получателем которого является Кнопка, в первой фазе event flow. А ваша конструкция не имеет инструментов различения фазы и принадлежности события, поэтому и "захватывает" всё подряд. Почитайте документацию о реализации событий в среде флеш.

По поводу вашего минифреймворка. Может я не правильно, или не до конца понял вашу мысль, но кажется, всё, каким-то... сложным. Я бы например делал бы так:

Код AS3:
   private function onClick( evt:MouseEvent ):void
  {
     // проверяет принадлежность объекта к какому-то классу или его предку
      if( !( evt.target is MenuClass ) ) return;
 
      //further processing
 
  }

Старый 18.04.2012, 01:13
s3dworld вне форума Посмотреть профиль Отправить личное сообщение для s3dworld Найти все сообщения от s3dworld
  № 6  
Ответить с цитированием
s3dworld

Регистрация: Apr 2010
Сообщений: 170
fish_r
Цитата:
Вот в том то и дело, что Меню рассылает событие получателем которого является Кнопка, в первой фазе event flow.
Так. У меня кнопка лежит в меню. Как меню рассылает кнопке? Это же восходящая цепочка. А мне нужна только нисходящая цепочка - чтобы от детей к родителям. Как этого добиться?

Старый 18.04.2012, 01:25
fish_r вне форума Посмотреть профиль Отправить личное сообщение для fish_r Посетить домашнюю страницу fish_r Найти все сообщения от fish_r
  № 7  
Ответить с цитированием
fish_r
 
Аватар для fish_r

блогер
Регистрация: Jan 2011
Сообщений: 1,162
Записей в блоге: 4
Вы не правильно понимаете модель распространения событий ( отображаемых объектов), поэтому и говорю, что вам нужно бы ознакомиться с ней, тогда всё станет яснее...

Меню не рассылает кнопке. Меню просто диспатчит событие двигающееся от стейджа к Кнопке. Ваша конструкция обрабатывает это событие так, как будет его получателем является Меню, а на деле это не так. Отсюда и путаница.

В общем случае обрабатывается это так:

Код AS3:
    private function onClick( evt:MouseEvent ):void
    {
        // проверяем - принадлежит ли полученное событие собственно Меню
         if( evt.target !== Menu ) return;
 
       // другой вариант, по фазе события: принадлежит ли событие объекту получателю
         if( evt.eventPhase !== EventPhase.AT_TARGET ) return;
 
    }
Добавлено через 11 минут
То есть я вас сейчас ещё больше запутаю

Второй вариант точнее сформулировать так: получено ли событие в фазе обработки получателем (если это одна из других двух фаз, захвата или всплытия - выходим без обработки).


Последний раз редактировалось fish_r; 18.04.2012 в 01:28.
Старый 18.04.2012, 01:37
s3dworld вне форума Посмотреть профиль Отправить личное сообщение для s3dworld Найти все сообщения от s3dworld
  № 8  
Ответить с цитированием
s3dworld

Регистрация: Apr 2010
Сообщений: 170
fish_r
Можете дать ссылку на статью, где понятным языком рассказано про события? Просто то что Вы написали, я не совсем понял.

Старый 18.04.2012, 01:40
fish_r вне форума Посмотреть профиль Отправить личное сообщение для fish_r Посетить домашнюю страницу fish_r Найти все сообщения от fish_r
  № 9  
Ответить с цитированием
fish_r
 
Аватар для fish_r

блогер
Регистрация: Jan 2011
Сообщений: 1,162
Записей в блоге: 4
Я, вообще, об этом ещё у Мука читал. Там довольно ясно описано. Ну вот есть в документации: http://help.adobe.com/ru_RU/as3/dev/...0204-7dfb.html. Ещё по форуму посмотрите, этот вопрос, конечно не однократно поднимался здесь.

Старый 18.04.2012, 01:56
s3dworld вне форума Посмотреть профиль Отправить личное сообщение для s3dworld Найти все сообщения от s3dworld
  № 10  
Ответить с цитированием
s3dworld

Регистрация: Apr 2010
Сообщений: 170
fish_r
Спасибо, завтра почитаю. Если будут вопросы, я сюда напишу.

Создать новую тему Ответ Часовой пояс GMT +4, время: 05:32.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 05:32.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.