Solved

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

Posted on 2008-10-24
2
599 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
ID: 22802042
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
ID: 22805820
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I come across a lot of question about how to access things in the document class from a movieclip, or accessing something from a movieclip in the document class. It took me a while to figure this out but once I did it makes life so much easier. …
In my long career of working as an actionscript developer, I had spent sleepless night often working hard to solve some small problems which actually took a lot of my development time; later found out the solutions to be a line or two. Here are s…
The goal of the tutorial is to teach the user how to select the video input device. Make sure you have an input device that in connected and work and recognized by Adobe Flash Media Live Encoder and select it in the “video input” menu.
The goal of the tutorial is to teach the user how to select which audio input to use. Once you have an audio input plugged into the laptop or computer, you will go into the audio input settings and choose which audio input you want to use.

895 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

14 Experts available now in Live!

Get 1:1 Help Now