Flash AS3 stack overflow - actionscript-3

I have this code for a login tutorial that I followed.
package {
/*
always extend a class using movieclip instead of sprite when using flash.
*/
import flash.display.MovieClip;
import flash.events.*;
import flash.net.*;
import flash.text.*;
/*
create our class
*/
public class login extends MovieClip {
;
public function login ():void {
var login_form:login = new login();
addChild(login_form);
var username:TextField = new TextField();
addChild(username);
var password:TextField = new TextField();
addChild(password);
var login_button:MovieClip = new MovieClip();
addChild(login_button);
/*
buttonMode gives the submit button a rollover
*/
login_button.buttonMode = true;
/*
what this says is that when our button is pressed, the checkLogin function will run
*/
login_button.addEventListener(MouseEvent.MOUSE_DOWN, checkLogin);
/*
set the initial textfield values
*/
username.text = "";
password.text = "";
}
public function checkLogin (e:MouseEvent):void {
var username:TextField = new TextField();
addChild(username);
var password:TextField = new TextField();
addChild(password);
/*
check fields before sending request to php
*/
if (username.text == "" || password.text == "") {
/*
if username or password fields are empty set error messages
*/
if (username.text == "") {
username.text = "Enter your username";
}
if (password.text == "") {
password.text = "Enter your password";
}
} else {
/*
init function to process login
*/
processLogin();
}
}
public function processLogin ():void {
var username:TextField = new TextField();
addChild(username);
var password:TextField = new TextField();
addChild(password);
/*
variables that we send to the php file
*/
var phpVars:URLVariables = new URLVariables();
/*
we create a URLRequest variable. This gets the php file path.
*/
var phpFileRequest:URLRequest = new URLRequest("php/controlpanel.php");
/*
this allows us to use the post function in php
*/
phpFileRequest.method = URLRequestMethod.POST;
/*
attach the php variables to the URLRequest
*/
phpFileRequest.data = phpVars;
/*
create a new loader to load and send our urlrequest
*/
var phpLoader:URLLoader = new URLLoader();
phpLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
phpLoader.addEventListener(Event.COMPLETE, showResult);
/*
now lets create the variables to send to the php file
*/
phpVars.systemCall = "checkLogin";
phpVars.username = username.text;
phpVars.password = password.text;
/*
this will start the communication between flash and php
*/
phpLoader.load(phpFileRequest);
}
public function showResult (event:Event):void {
var result_text:TextField = new TextField();
addChild(result_text);
/*
this autosizes the text field
***** You will need to import flash's text classes. You can do this by adding:
import flash.text.*;
...to your list of import statements
*/
result_text.autoSize = TextFieldAutoSize.LEFT;
/*
this gets the output and displays it in the result text field
*/
result_text.text = "" + event.target.data.systemResult;
}
}
}
I'm not exactly sure where to put all those instances for my button movieclip and text field but when I ran my program, I got this error.
Error: Error #1023: Stack overflow occurred.
at flash.display::DisplayObject()
at flash.display::InteractiveObject()
at flash.text::TextField()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
at login()
I tried searching answers that I could understand but to no avail. Any help would be appreciated, thank you.

You got the Stack overflow error because you are creating an infinite loop of instantiating your login class using var login_form:login = new login(); in its constructor, so every instance of that class will create another instance.
You should instantiate your class only when/where you want to insert it, for example, in the main timeline, or the document class, ..., or just by dropping it directly to the stage.
But before instantiating the login class, you should create it correctly. For that, you can add your objects (Buttons, MovieClips, TextFields, ...) manually in your IDE by dropping them to the stage of your MovieClip, or by code using for example :
var username:TextField = new TextField();
addChild(username);
var password:TextField = new TextField();
addChild(password);
// LoginButton here is the AS linkage of a MovieClip/Button in the library
var login_button:LoginButton = new LoginButton();
addChild(login_button);
this operation is usually done once, then you can use your objects like this for example :
var user_name:String = username.text;
if(password.text != ''){ /* ... */ }
login_button.x = 30;
As you are beginner, you can start Learning ActionScript 3 here.
Hope that can help.

You seem to be creating an instance of the login class and adding it to itself which is causing the infinite recursion in the login constructor.
var login_form:login = new login();
You should initialize the login class from another object and add it to the stage just once.

Related

Flash AS3 class

So I'm new to Flash and I'm currently following a tutorial about login and registration.
The tutorial that I followed has an external AS file just like this :
where I type the name of the class in the space given. So far, when I run the program, it gives me the correct output.
Now here comes my problem. I've made some modifications to the way it references(?) the class, which in this case, I export the class just like this in the symbols properties. And now, the code won't work and I've been trying to figure this out for about 5 hours already and I can't seem to get it done.
Here's the image of me adding the class in the symbols properties :
And here is my login class :
package {
/*
always extend a class using movieclip instead of sprite when using flash.
*/
import flash.display.MovieClip;
import flash.events.*;
import flash.net.*;
import flash.text.*;
/*
create our class
*/
public class login extends MovieClip {
public function login(): void {
/*
buttonMode gives the submit button a rollover
*/
login_button.buttonMode = true;
/*
what this says is that when our button is pressed, the checkLogin function will run
*/
login_button.addEventListener(MouseEvent.MOUSE_DOWN, checkLogin);
/*
set the initial textfield values
*/
username.text = "";
password.text = "";
}
public function checkLogin(e: MouseEvent): void {
/*
check fields before sending request to php
*/
if (username.text == "" || password.text == "") {
/*
if username or password fields are empty set error messages
*/
if (username.text == "") {
username.text = "Enter your username";
trace(success);
}
if (password.text == "") {
password.text = "Enter your password";
}
} else {
/*
init function to process login
*/
processLogin();
}
}
public function processLogin(): void {
/*
variables that we send to the php file
*/
var phpVars: URLVariables = new URLVariables();
/*
we create a URLRequest variable. This gets the php file path.
*/
var phpFileRequest: URLRequest = new URLRequest("php/controlpanel.php");
/*
this allows us to use the post function in php
*/
phpFileRequest.method = URLRequestMethod.POST;
/*
attach the php variables to the URLRequest
*/
phpFileRequest.data = phpVars;
/*
create a new loader to load and send our urlrequest
*/
var phpLoader: URLLoader = new URLLoader();
phpLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
phpLoader.addEventListener(Event.COMPLETE, showResult);
/*
now lets create the variables to send to the php file
*/
phpVars.systemCall = "checkLogin";
phpVars.username = username.text;
phpVars.password = password.text;
/*
this will start the communication between flash and php
*/
phpLoader.load(phpFileRequest);
}
public function showResult(event: Event): void {
/*
this autosizes the text field
***** You will need to import flash's text classes. You can do this by adding:
import flash.text.*;
...to your list of import statements
*/
result_text.autoSize = TextFieldAutoSize.LEFT;
/*
this gets the output and displays it in the result text field
*/
result_text.text = "" + event.target.data.systemResult;
trace(success);
}
}
}
Edit :
Here is the picture where the base class just disappears :
Thanks for the help.

How do i access a file that is loaded after?

This is in Flash Action Script 3
Here is my class, I loaded an xml in the class
and now i want to do some things after in the main page, like create things on the stage based off of the xml. Help
I understand why it doesn't work, by the time the function is called the xml hasn't be loaded yet, i'm just clueless how to solve this? add an event listener maybe?
package {
public class LoadXMLAdventure {
var adventureXML: XML;
var xmlReq:URLRequest;
var xmlLoader:URLLoader = new URLLoader();
var _currentRoom:int;
public function LoadXMLAdventure(xmlFileName:String) {
xmlReq = new URLRequest(xmlFileName);
xmlLoader.load(xmlReq);
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
}
function xmlLoaded(event:Event):void{
adventureXML = new XML(xmlLoader.data)
//trace( adventureXML.toXMLString() )
}
public function myFunction():void{
trace(adventureXML.toXMLString()) //this does not work
}
}
}
On my main page
var game:LoadXMLAdventure = new LoadXMLAdventure("file.xml");
game.myFunction();
Update
I want to call a function on the main page so i can do some stage manipulation
this is in the class, i get an error undefined method
function xmlLoaded(event:Event):void{
adventureXML = new XML(xmlLoader.data)
this.dispatchEvent( new Event("showRoom") );
}
this is on the stage
stage.addEventListener("showRoom",showRoom);
function showRoom(e:Event):void{
trace("showroom hello")
}
You can dispatch an event when the xml loaded complete,but in your case, you just need to call myFunction in xmlLoaded;
import flash.events.EventDispatcher;
public class LoadXMLAdventure extends EventDispatcher{
public function LoadXMLAdventure(xmlFileName:String) {
xmlReq = new URLRequest(xmlFileName);
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
}
public function startLoad():void {
xmlLoader.load(xmlReq);
}
function xmlLoaded(event:Event):void{
adventureXML = new XML(xmlLoader.data);
this.dispatchEvent(new Event("LoadXmlComplete"));
}
}
Here is how to use
var game:LoadXMLAdventure = new LoadXMLAdventure("file.xml");
game.addEventListener("LoadXmlComplete", onComplete);
game.startLoad();
private function onComplete(e:Event):void {
//do some thing
}

Receiving a stream of a NetGroup

I'm trying to receive a stream of a NetGroup (television) but it fails at some point. Here is the code (reduced to a testcase):
package lib
{
import flash.events.NetStatusEvent;
import flash.external.ExternalInterface;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.GroupSpecifier;
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.NetStream;
import flash.net.NetStreamPlayOptions;
import mx.core.FlexGlobals;
public class player
{
private var connection:NetConnection;
private var group:NetGroup;
private var group_option:GroupSpecifier;
private var self:Object;
private var stream:NetStream;
private var stream_option:NetStreamPlayOptions;
private var video:Video;
private function _connect():void
{
self.connection = new NetConnection();
self.connection.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
self.connection.connect('rtmfp://p2p.peer-stream.com');
}
private function _event_net_status(event:NetStatusEvent):void
{
if(event.info.code === '')
return;
ExternalInterface.call('echo', 'status', event.info.code, false);
switch(event.info.code)
{
case 'NetConnection.Connect.Success':
self._p2p_start();
break;
case 'NetGroup.Connect.Success':
self._stream_init();
break;
case 'NetStream.Connect.Success':
self._stream_start();
break;
}
}
private function _p2p_start():void
{
self.group_option = new GroupSpecifier('G:0101010c0b0e70726f2073696562656e00');
self.group_option.ipMulticastMemberUpdatesEnabled = true;
self.group_option.multicastEnabled = true;
self.group_option.objectReplicationEnabled = true;
self.group_option.postingEnabled = true;
self.group_option.routingEnabled = true;
self.group_option.serverChannelEnabled = true;
self.group = new NetGroup(self.connection, self.group_option.groupspecWithAuthorizations());
self.group.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_init():void
{
self.stream = new NetStream(self.connection, self.group_option.groupspecWithAuthorizations());
self.stream.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_start():void
{
self.video.attachNetStream(self.stream);
self.stream.soundTransform = new SoundTransform();
self.stream_option = new NetStreamPlayOptions();
self.stream_option.streamName = 'G:0101010c0b0e70726f2073696562656e00';
self.stream.play2(self.stream_option);
}
public function player():void
{
super();
FlexGlobals.topLevelApplication.stage.quality = 'BEST';
self = this;
self.video = new Video(640, 480);
FlexGlobals.topLevelApplication.video_box.addChild(self.video);
self.video.smoothing = true;
self._connect();
}
}
}
The ExternalInterface call there shows me just the passed info in a textfield (I'm testing this in a browser). Here is the result of this output:
NetConnection.Connect.Success
NetGroup.Connect.Success
NetStream.Connect.Success
NetStream.Play.Reset
NetStream.Play.Start
But nothing happens on the player. Here are my thoughts:
I'm using the same string as GroupSpecifier and streamName but I'm assuming this is wrong. If so how can I get the stream name of the NetGroup?
I'm enabling everything from the GroupSpecifier as I don't know what are the minimum requirements to receive a stream and pass it then to another clients. Maybe enabling all makes some troubles here.
Maybe somebody can tell me how I can solve this problem to finally see a stream.
I was able to solve the problem: The streamName was indeed wrong and I could manually figure out the correct name. Also instead of using new GroupSpecifier() I must pass the known group-string directly to the NetGroup and NetStream object.

Broadcast Custom Event from Model

`My "Model" is an AS class that extends EventDispatcher:
MeetingInfoModel extends EventDispatcher
In this class I broadcast a custom event:
var eventObj:CustomEvent = new CustomEvent( CustomEvent.UPDATE_DOC_COUNTER );
dispatchEvent( eventObj );
I include a metadata tag at top of class:
[Event(name="updateDocCounter", type="com.fmr.transporter.events.CustomEvent")]
I attempt to listen to for this event in an MXML component:
this.addEventListener( CustomEvent.UPDATE_DOC_COUNTER, onDocUpdate );
But it never reaches this listener.
I've run into issues like this a lot and I think there's a crucial part of the Event process that I'm just not understanding.
Can anyone provide any helpful clues, please?
Thank you!
UPDATE:
In response to all the comments below (thank you for all the responses!):
MeetingInfoModel is not a display component and shouldn't be responsible for broadcasting events; that's the piece I was not getting!!
Here's my code: In the MeetingInfoModel constructor I listen for the collection change event of one of its class members:
docsAndAttachmentsList.addEventListener( CollectionEvent.COLLECTION_CHANGE, updateDocsCounter );
In that handler I try to broadcast an event that an MXML component (that is part of the display hierarchy) will handle:
private function updateDocsCounter( event:CollectionEvent ):void
{
var eventObj:CustomEvent = new CustomEvent( CustomEvent.UPDATE_DOC_COUNTER );
dispatchEvent( eventObj );
}
Back in the MXML component, I call this method from the creationComplete handler:
private function addListeners():void{
MeetingInfoModel.getInstance().addEventListener( CustomEvent.UPDATE_DOC_COUNTER, onDocUpdate );
}
It sounds like I should just listen for the collection change event on the MXML component. I tried that but it doesn't work:
MeetingInfo.getInstance().docsAndAttachmentsList.addEventListener( CollectionEvent.COLLECTION_CHANGE, updateDocsCounter );
I don't know why that's not working; it seems to be the best solution.
Here's the full MeetingInfoModel class:
[Bindable]
[Event(name="updateDocCounter", type="com.fmr.transporter.events.CustomEvent")]
public final class MeetingInfoModel extends EventDispatcher
{
//Universal INFO
public var generalInfo:GeneralInfoModel;
public var meetingVO:MeetingVO = new MeetingVO();
public var meetingId:String;
public var bulletinBoardLiveMembers:ArrayCollection = new ArrayCollection();
public var xmppServices:XMPPServices;
public var declinedParticipantsGroup:ArrayCollection = new ArrayCollection();
public var notJoinedParticipantsGroup:ArrayCollection = new ArrayCollection();
public var conferenceRoomParticipantsGroup:ArrayCollection = new ArrayCollection();
public var otherLocationParticipantsGroup:ArrayCollection = new ArrayCollection();
[Bindable]
public var documentList:ArrayCollection = new ArrayCollection();
[BIndable]
public var newAttachmentList:ArrayCollection = new ArrayCollection();
public var docsAndAttachmentsList:ArrayCollection = new ArrayCollection();
public var bulletinBoardMsgList:ArrayCollection = new ArrayCollection();
private var _participantList:ArrayCollection = new ArrayCollection();
public var dismissedMeetingIDs:Array = [];
public var visibleToastWindows:Array = [];
public function MeetingInfoModel()
{
generalInfo = GeneralInfoModel.getInstance();
xmppServices = XMPPServices.getInstance();
_participantList.addEventListener(CollectionEvent.COLLECTION_CHANGE, allParticipantsChangeHandler);
bulletinBoardLiveMembers.addEventListener(CollectionEvent.COLLECTION_CHANGE, bulletinBoardLiveMembersChangeHandler);
docsAndAttachmentsList.addEventListener( CollectionEvent.COLLECTION_CHANGE, updateDocsCounter );
}
private static var model:MeetingInfoModel = null;
public static function getInstance():MeetingInfoModel
{
if (model == null)
{
model = new MeetingInfoModel();
}
return model;
}
/**
* The handler for the collection change event of the docsAndAttachmentsList collection.
*
* We use it to manually update the counter on the Docs tab.
*/
private function updateDocsCounter( event:CollectionEvent ):void
{
var eventObj:CustomEvent = new CustomEvent( CustomEvent.UPDATE_DOC_COUNTER );
dispatchEvent( eventObj );
}
public function displayToastForThisMeeting(meetingID:Number):Boolean
{
//trace("model::meetingID = " + meetingID);
var doDisplayToast:Boolean = false;
var containsMeetingID:Boolean = false;
//the first one
if(dismissedMeetingIDs.length == 0)
{
//trace("dismissedMeetingIDs.length = 0");
doDisplayToast = true;
dismissedMeetingIDs.push(meetingID);
}
else
{
for(var i:int=0; i < dismissedMeetingIDs.length; i++)
{
//trace("dismissedMeetingIDs[" + i + "] = " + dismissedMeetingIDs[i]);
if(meetingID == dismissedMeetingIDs[i])
{ //this one has already been dismissed
doDisplayToast = false;
containsMeetingID = true;
break;
}
else
{
doDisplayToast = true;
containsMeetingID = false;
}
}
if(containsMeetingID == false)
{
dismissedMeetingIDs.push(meetingID);
}
}
return doDisplayToast;
}
}
Here's some code from my MXML component (whose base class is Group):
import com.fmr.transporter.controller.TransporterController;
import com.fmr.transporter.events.CustomEvent;
import com.fmr.transporter.model.MeetingInfoModel;
import com.fmr.transporter.model.TransporterModel;
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.events.CollectionEvent;
import mx.events.FlexEvent;
private var controller:TransporterController;
[Bindable] public var newAttachmentsList:ArrayCollection;
[Bindable] public var meetingInfo:MeetingInfoModel;
private function complete():void
{
controller = TransporterController.getInstance();
addListeners();
}
/** Add listeners to this class.
*/
private function addListeners():void{
MeetingInfo.getInstance().docsAndAttachmentsList.addEventListener( CollectionEvent.COLLECTION_CHANGE, updateDocsCounter );
}
You extended the event class. By default, flex event don't bubble. You need to modify your CustomEvent class constructor to look like this:
public function CustomEvent(type:String){
super(type, true, true);
}
This will make your event bubble and also cancelable per flex event framework. #The_asMan told you correctly about how to deal with a non bubbling event, but I think you may have accidentally missed the right object. Make it bubble and you will hear it!!
#LondonDrugs_MediaServices, #Flextras, and #The_asMan.
These guys are right; it doesn't appear that the class has to be on the display list in order for the event to be listened for. As long as you have the correct target for the class dispatching the event it should be just fine.
For some reason, though, I've done something really weird and couldn't quite figure it out in the end. The solution was to use binding on the collection I updated in the model in order to update the component I wanted.
Thank you everyone for your very helpful comments.

flex 4: window system development ideas

My application will need some windows but I can't use the popUpManager to handle custom components so I'm thinking to implement a new window system.
But I still don't know how to merge it with my custom components. Any ideas?
My code:
My login skin:
<s:Skin(...)>
<s:Group>
(...login components...)
</s:Group>
</s:Skin>
package com.totty.app.components.login {
import com.totty.app.TottysBrain;
import com.totty.app.components.window.Window;
import com.totty.app.events.LoginSuccessEvent;
import com.totty.tottysBrain.components.BrainyDynComponent;
import com.totty.tottysBrain.components.BrainyWindow;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.Alert;
import mx.managers.PopUpManager;
import spark.components.Button;
import spark.components.CheckBox;
import spark.components.Group;
import spark.components.Label;
import spark.components.TextInput;
import spark.components.supportClasses.SkinnableComponent;
[Event(name="loginSuccess", type="com.totty.app.events.LoginSuccessEvent")]
public class Login extends BrainyDynComponent {
[SkinPart(required="true")]
public var email:TextInput;
[SkinPart(required="true")]
public var password:TextInput = new TextInput();
[SkinPart(required="false")]
public var rememberMe:CheckBox;
[SkinPart(required="false")]
public var notification:Label;
[SkinPart(required="true")]
public var submit:Button = new Button();
private var _currentState:uint = 0;
private var _states:Array = ['default', 'logging', 'loginFailure', 'loginSuccess'];
private var _default:Boolean = false;
private var _logging:Boolean = false;
private var _loggingSuccess:Boolean = false;
private var _loggingFailure:Boolean = false;
public function Login() {
super();
defaultCommand = 'users.login';
defaultSkin = LoginSkin;
_setCurrentState(0);
onPartAdded('submit', function():void {
submit.addEventListener(MouseEvent.CLICK, _submitLoginButton_click);
});
onPartRemoved('submit', function():void {
submit.removeEventListener(MouseEvent.CLICK, _submitLoginButton_click);
});
onPartAdded('window', function():void{
//window.addEventListener('close', _window_close);
//window.title = 'Login';
});
}
private function _window_close(evt:Event):void{
dispatchEvent(evt);
var parentAsGroup:Group = parent as Group
parentAsGroup.removeElement(this);
}
protected function _submitLogin():void {
_setCurrentState(1);
submitData({email:email.text, password:password.text, rememberMe:rememberMe.selected});
}
override protected function _onSuccess(result:*):void {
Alert.show(result);
_setCurrentState(3);
if(result) {
dispatchEvent(new LoginSuccessEvent(email.text, rememberMe.selected));
_loggingSuccess = true;
}else{
_setCurrentState(4);
_loggingSuccess = false;
}
}
override protected function _onFailure(result:*):void {
Alert.show(result);
_setCurrentState(4);
_loggingSuccess = false;
}
private function _submitLoginButton_click(evt:MouseEvent):void {
_submitLogin();
}
private function _setCurrentState(n:uint):void{
if(_currentState == n) return;
_currentState = n;
invalidateProperties();
}
override protected function commitProperties():void{
super.commitProperties();
switch(_currentState){
case 0:
// default
//window.footerText = '';
break;
case 1:
// logging
//window.footerText = 'logging';
break;
case 2:
// loginFailure
//window.footerText = 'loginFailure';
break;
case 3:
// loginSuccess
//window.footerText = 'loginSuccess';
//parentBrain.removeElement(this);
//var parentAsGroup:Group = parent as Group
//PopUpManager.removePopUp(this);
//parentAsGroup.removeElement(this);
break;
}
}
}
}`
Now I have the main application to add this component in a window. I would prefer to be able to be able to see the window while I'm designing the interface. That means that the window component must be added to the component. Not to use the but something like to contain all the contents of the component.
Maybe you already saw this, but its a good place to start, anyway :)
http://code.google.com/p/flexmdi/