Solved

Why Isn't MouseEvent.ROLL_OVER/OUT Firing Consistantly?  I Just Want to Do a Simple Toggle!

Posted on 2008-10-24
2
597 Views
Last Modified: 2013-11-11
I working on a VideoScreen component, which at this point just extends UIComponent and contains a Video object as its first child. After the Video is added to the stage, I create an overlay using a Sprite object. The overlay isn't added to the stage until the user does a MouseEvent.ROLL_OVER the VideoScreen component. The overlay is removed from the stage on MouseEvent.ROLL_OUT.

The problem here is that sometimes the MouseEvent.ROLL_OVER doesn't fire, which throws the toggle off (ROLL_OUT will add the overlay to the stage instead of removing it). Can you help me figure this out?

Here is some of my debugging output; in this case the error happens just after COUNT 2 where two 'ROLL_OUT' events are fired without a 'ROLL_OVER' between them:

----------------------------------------------------------
VideoScreen mouseRollOverOutListener COUNT: 1      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOver" bubbles=false cancelable=false eventPhase=2 localX=16 localY=62 stageX=16 stageY=62 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Showing overlay (expecting FALSE)...      _isShowingOverlay current value: false
Overlay should now be TRUE      _isShowingOverlay: true

VideoScreen mouseRollOverOutListener COUNT: 2      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOut" bubbles=false cancelable=false eventPhase=2 localX=-1 localY=-1 stageX=-1 stageY=-1 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Hiding overlay (expecting TRUE)...      _isShowingOverlay current value: true
Overlay should now be FALSE      _isShowingOverlay: false

VideoScreen mouseRollOverOutListener COUNT: 3      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOut" bubbles=false cancelable=false eventPhase=2 localX=-1 localY=-1 stageX=-1 stageY=-1 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Showing overlay (expecting FALSE)...      _isShowingOverlay current value: false
Overlay should now be TRUE      _isShowingOverlay: true

VideoScreen mouseRollOverOutListener COUNT: 4      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOver" bubbles=false cancelable=false eventPhase=2 localX=2 localY=69 stageX=2 stageY=69 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Hiding overlay (expecting TRUE)...      _isShowingOverlay current value: true
Overlay should now be FALSE      _isShowingOverlay: false

VideoScreen mouseRollOverOutListener COUNT: 5      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOut" bubbles=false cancelable=false eventPhase=2 localX=-1 localY=-1 stageX=-1 stageY=-1 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Showing overlay (expecting FALSE)...      _isShowingOverlay current value: false
Overlay should now be TRUE      _isShowingOverlay: true

VideoScreen mouseRollOverOutListener COUNT: 6      (Odd numbers should always be MouseEvent type='rollOver')
[MouseEvent type="rollOver" bubbles=false cancelable=false eventPhase=2 localX=8 localY=78 stageX=8 stageY=78 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
Hiding overlay (expecting TRUE)...      _isShowingOverlay current value: true
Overlay should now be FALSE      _isShowingOverlay: false
----------------------------------------------------------

Here is the VideoScreen; just place it in a project sub-folder called 'controls' and use it as MXML:

<controls:VideoScreen id="videoScreen" width="300" height="225" fixDistortion="true" />





package com.futurewebstudios.controls

{

	import flash.display.Sprite;

	import flash.events.Event;

	import flash.events.MouseEvent;

	import flash.media.Video;

	import flash.net.NetStream;

	

	import mx.core.UIComponent;

	import mx.events.FlexEvent;
 

	public class VideoScreen extends UIComponent

	{

		

    //--------------------------------------------------------------------------

    //  Private properties

    //--------------------------------------------------------------------------		

		private const DEFAULT_WIDTH:Number = 320;

		private const DEFAULT_HEIGHT:Number = 240;

		private var _video:Video;

		private var _videoIsDistorted:Boolean;

		private var _overlay:Sprite;

		private var _isShowingOverlay:Boolean;

		private var _overlayShowCount:uint = 1;

		private var _stream:NetStream;

		private var _streamIsChanged:Boolean;  //changes to true once set, to false after used

		private var _maintainAspectRatio:Boolean; //needs no boolean state value; handled on property change

		

    //--------------------------------------------------------------------------

    //  Public properties

    //--------------------------------------------------------------------------

		[Bindable( event="videoIsDistortedChanged" )]

		[Inspectable( defaultValue="false" )]

		public function set fixDistortion( value:Boolean ):void

		{

			if ( _videoIsDistorted != value )

			{

				_videoIsDistorted = value;

			}

		}

		public function get fixDistortion():Boolean

		{

			return _videoIsDistorted;

		}

		

		[Bindable( event="streamChanged" )]

		[Inspectable( category="General", defaultValue="null" )]

		public function set stream( value:NetStream ):void

		{

	        if ( _stream != value )

	        {

	        	_stream = value;

	        	_streamIsChanged = true;

	         	dispatchEvent( new Event( "streamChanged" ) );   

	        }

		}

		public function get stream():NetStream

		{

			return _stream;

		}

		

		[Bindable( "maintainAspectRatioChanged" )]

		[Inspectable( defaultValue="true" )]

		public function set maintainAspectRatio( value:Boolean ):void

		{

			if ( _maintainAspectRatio != value )

			{

				_maintainAspectRatio = value;

				invalidateSize();

				invalidateDisplayList();

				dispatchEvent( new Event( "maintainAspectRatioChanged" ) );

			}

		}

		public function get maintainAspectRatio():Boolean

		{

			return _maintainAspectRatio;

		}

		

		 public function get  isShowingOverlay():Boolean

		 {

		 	return _isShowingOverlay;

		 }

	    

    //--------------------------------------------------------------------------

    //  Constructor

    //--------------------------------------------------------------------------

		public function VideoScreen()

		{

			this.addEventListener( FlexEvent.INITIALIZE, initializeListener );

			this.addEventListener( MouseEvent.ROLL_OVER, mouseRollOverOutListener );

			this.addEventListener( MouseEvent.ROLL_OUT, mouseRollOverOutListener );

			

			_video = new Video( this.DEFAULT_WIDTH, this.DEFAULT_HEIGHT );

			this.addChild( _video );

			

			super();

		}

		

    //--------------------------------------------------------------------------

    //  Public methods

    //--------------------------------------------------------------------------

	    public function attachNetStream( value:NetStream ):void

	    {

	    	_video.attachNetStream( value );

	    }

		public function showOverlay():void

		{

			if ( _isShowingOverlay == false )

			{

				trace( "Showing overlay (expecting FALSE)...\t_isShowingOverlay current value: " + _isShowingOverlay );

				_isShowingOverlay = true;

				addChild( _overlay );

				trace( "Overlay should now be TRUE\t\t\t_isShowingOverlay: " + _isShowingOverlay );

			}

			else

			{

				trace( "ERROR!!  _isShowingOverlay returns TRUE from showOverlay()" );

			}

		}

		public function hideOverlay():void

		{

			if ( _isShowingOverlay == true )

			{

				trace( "Hiding overlay (expecting TRUE)...\t\t_isShowingOverlay current value: " + _isShowingOverlay );

				_isShowingOverlay = false;

				removeChild( _overlay );

				trace( "Overlay should now be FALSE\t\t\t_isShowingOverlay: " + _isShowingOverlay );

			}

			else

			{

				trace( "ERROR!!  _isShowingOverlay returns FALSE from hideOverlay()" );

			}			

		}

	    

    //--------------------------------------------------------------------------

    //  Protected methods

    //--------------------------------------------------------------------------

		protected function setPublicValues():void

		{

			_video.width = this.width;

			_video.height = this.height;

			if ( _videoIsDistorted )

			{

				_video.smoothing = true;

			}

		}

		protected function createOverlay():void

		{

			_overlay = new Sprite();

			_overlay.graphics.beginFill( 0x000000, .5 );

			_overlay.graphics.drawRect( 0, 0,  this.width, this.height );

			_overlay.graphics.endFill();

			

			_isShowingOverlay = false;

			trace( "createOverlay() done.  Initial value should be false.  VALUE: " + _isShowingOverlay );

		}

		

    //--------------------------------------------------------------------------

    //  Private methods

    //--------------------------------------------------------------------------

		private function initializeListener( e:FlexEvent ):void

		{

			setPublicValues();

			createOverlay();

		}

		private function mouseRollOverOutListener( e:MouseEvent ):void

		{

			trace( "\nVideoScreen mouseRollOverOutListener COUNT: " + ( _overlayShowCount++ ) + "\t\t(Odd numbers should always be MouseEvent type='rollOver')\n" + e.toString() );

			( _isShowingOverlay == false ) ? showOverlay() : hideOverlay();

		}

	}

}

Open in new window

0
Comment
Question by:JaeWebb
2 Comments
 
LVL 19

Accepted Solution

by:
Gary Benade earned 500 total points
Comment Utility
When you add the overlay as a child it effectively hijacks mouse events to the video control because it's on top of it, one way to fix this is to add the same event listeners to overlay as the video like below, another is to set overlay.mouseEnabled = false;


protected function createOverlay():void

                {

                        _overlay = new Sprite();

                        _overlay.graphics.beginFill( 0x000000, .5 );

                        _overlay.graphics.drawRect( 0, 0,  this.width, this.height );

                        _overlay.graphics.endFill();

                        

                        _isShowingOverlay = false;

                        trace( "createOverlay() done.  Initial value should be false.  VALUE: " + _isShowingOverlay );
 

                        overlay.addEventListener( MouseEvent.ROLL_OVER, mouseRollOverOutListener );

                        overlay.addEventListener( MouseEvent.ROLL_OUT, mouseRollOverOutListener );
 

                }

Open in new window

0
 

Author Comment

by:JaeWebb
Comment Utility
If you notice the constructor, the component itself is the object listening for the events.  The video player is the first child, the overlay is the second child.  The target and current target of the MouseEvent.ROLL_OVER/OUT are always the VideoScreen component itself, never its children.  ROLL_OVER/OUT events do not bubble either.

When I follow your first suggestion and add event listeners to the overlays, the mouseRollOverOutListener is fired a bunch of times.  Just two quick swipes over the Screen produces this:

-- VideoScreen mouseRollOverOutListener --
COUNT: 89, EVENT TYPE: rollOver            (Odd numbers should always be MouseEvent type='rollOver')
Showing overlay (expecting FALSE)...      _isShowingOverlay current value: false
Overlay should now be TRUE                  _isShowingOverlay: true

-- VideoScreen mouseRollOverOutListener --
COUNT: 90, EVENT TYPE: rollOver            (Odd numbers should always be MouseEvent type='rollOver')
Hiding overlay (expecting TRUE)...            _isShowingOverlay current value: true
Overlay should now be FALSE                  _isShowingOverlay: false


When I remove the listeners at the component level and keep them on the overlays, the listener is never triggered.  When I listen for ROLL_OVER at the component level and OUT at the overlay level, I get crazy results - same thing reversed.  When I listen for ROLL_OVER on the video and ROLL_OUT on the overlay, I'm I don't get the results I expect.


When I tried your second idea and set mouseEnabled on the overlay to false, it worked as expected!  Your solution worked.   Thanks a lot.  I don't understand it since the listeners were at the container level and not at the children level, but hey - it works.

I am a bit worried about turning off the mouseEnabled property on the overlay though.  I'd like to emulate the functionality on this player:

http://www.huffingtonpost.com/2008/10/25/obama-mccain-target-the-w_n_137781.html

As you can see, when you mouseover the overlay close to the button, the button grows in response... That button must not be a child of the overlay as I originally assumed it was.  Any thoughts?  

Thanks again.


0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

First things first - Preparation We need all the part for this install and it's much nicer to have them all on hand when you need them so here's what's required. Download Eclipse 3.5 32 bit (I like the Classic flavour) from here. (http://www.e…
Sometimes you know that one object has a specific child in it, but you can't find the child. This happened to me when I was trying to code some actionScript to make a toolbar work with its embedded buttons.  My partner had created the toolbar usi…
In this tutorial viewers will learn how to create a basic motion tween animation in Flash Open a new document in Flash: Draw/import an image: Press CTRL + F8 to convert it into a graphic symbol: Select a frame (how long you want the tween to last): …
The goal of the tutorial is to teach the user how to set there setting in Adobe Flash Media Live Encoder and YouTube for optimal video and audio quality.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now