I have a movieClip within another MovieClip. I gave the child movieClip the instance name "hSprite" and I added it to the parent movieClip stage. Now I get an error like the following.
[Fault] exception, information=ReferenceError: Error #1056: Cannot create property hSprite on com.objects.Hero.
If I remove the instance name from the child movieclip, then the error goes away. but when I add the instance name back, the error reappears again.
Keep in mind that both classes are set for export.
The parent class is embeded by a custom class which work perfectly fine. But the minute I give the child movieClip a instance name, the error starts up again.
Here is the class that embeds the parent class. What I initially want to do is access the child MovieClip that is in the Hero symbol
package com.objects
{
import flash.display.MovieClip;
import flash.events.*;
/**
* ...
* #author Anthony Gordon
*/
[Embed(source='../../../bin/Assets.swf', symbol='Hero')]
public class Hero extends GameObject
{
private var aKeyPress:Array;
private var jumpDisabled:Boolean = false;
//private var heroSprite:MovieClip;
public function Hero()
{
wY = 150;
wX = 90;
speed = .5;
aKeyPress = new Array();
TheGame.sr.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
TheGame.sr.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
}
private function keyDownListener(e:KeyboardEvent):void {
//trace("down e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=true;
}
private function keyUpListener(e:KeyboardEvent):void {
//trace("up e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=false;
}
override public function UpdateObject():void
{
Controls();
updatePosition();
}
private function Controls():void
{
if (aKeyPress[38])//Key press up
;//dy -= speed;
else if (aKeyPress[40])//Key press down
dy += speed;
if (aKeyPress[37])//left
{
dx -= speed;
}
else if (aKeyPress[39])//Right
{
dx += speed;
}
if (aKeyPress[32]){//space
jump();
}
}//End Controls
private function jump():void
{
if (!jumpDisabled)
{
if (onGround)
{
dy = -15;
jumpDisabled = true;
}
}
else
{
jumpDisabled = false;
}
}
}
}
You need to make the hSprite clip a public variable in the class.
public var hSprite:MovieClip;
Related
I am working on upgrading Flex 3.0 application to Flex 3.6 SDK. The application has custom controls for input text, combo-boxes, etc. When I click on the combo-box I get exception when super.commitProperties() is called. This works fine with Flex 3.0 SDK.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.controls::ComboBox/destroyDropdown()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBox.as:1681]
at mx.controls::ComboBox/styleChanged()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBox.as:1177]
at mx.core::UIComponent/setBorderColorForErrorString()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\core\UIComponent.as:5048]
at mx.core::UIComponent/commitProperties()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\core\UIComponent.as:6033]
at mx.controls::ComboBase/commitProperties()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBase.as:993]
at mx.controls::ComboBox/commitProperties()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBox.as:1291]
at com.hanover.utility.controls.autotestcontrols::AutotestComboBox/commitProperties()[C:\App\Control\PLCustomComboBox.as:59]
at mx.core::UIComponent/validateProperties()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\core\UIComponent.as:5966]
at mx.managers::LayoutManager/validateProperties()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:539]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:689]
at mx.managers::LayoutManager/validateNow()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\managers\LayoutManager.as:748]
at mx.controls::ComboBox/displayDropdown()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBox.as:1638]
at mx.controls::ComboBox/downArrowButton_buttonDownHandler()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBox.as:1796]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\core\UIComponent.as:9590]
at mx.controls::Button/http://www.adobe.com/2006/flex/mx/internal::buttonPressed()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\Button.as:2504]
at mx.controls::Button/mouseDownHandler()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\Button.as:2750]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\core\UIComponent.as:9590]
at mx.controls::ComboBase/textInput_mouseEventHandler()[C:\autobuild\3.x\frameworks\projects\framework\src\mx\controls\ComboBase.as:1384]
PLCustomCombobox.as pseudo-source with line # 59 indicated below
package com
{
import com.name.utility.events.PLControlEvent;
import com.name.utility.managers.ComboToolTipManager;
import flash.events.Event;
import mx.controls.ComboBox;
import mx.events.FlexEvent;
[Event(name="controlInitComplete", type="com.events.PLControlEvent")]
[Event(name="plusControlValueChanged", type="com.name.utility.events.PLControlEvent")]
public class PLControlComboBox extends ComboBox
implements IPLControlControl
{
/**
* A flag that indicates whether the control need to refresh.
*/
protected var isNeedRefresh:Boolean = false;
/**
* A flag that indicates whether the value of control is changed.
*/
protected var isValueChanged:Boolean = false;
/**
* Constructor.
*/
public function PLControlComboBox()
{
super();
this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
/**
* #private
* override commitProperties for avoid dispatch event many times.
*/
override protected function commitProperties():void
{
super.commitProperties(); // <---- line # 59 is here
if(isNeedRefresh)
{
this.dispatchEvent(new PLControlEvent(PLControlEvent.VALUE_CHANGED));
isNeedRefresh = false;
}
if(isValueChanged)
{
this.dispatchEvent(new Event("PLControlComboboxChanged"));
isValueChanged = false;
}
}
/**
* Add item's tooltip.
* #private
*/
override public function set measuredWidth(value:Number):void
{
super.measuredWidth = value;
if(collection && collection.length > 0)
{
ComboToolTipManager.showItemToolTip(this);
}
}
protected function onCreationComplete(event:FlexEvent):void
{
this.removeEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
this.dispatchEvent(new PLControlEvent(PLControlEvent.INIT_COMPLETE));
}
public function checkValidity():void
{
if(_required && dataProvider && dataProvider.length > 0 && _defaultItemIndex == selectedIndex)
{
_validity = false;
errorString = "please select one";
}
else
{
_validity = true;
errorString = "";
}
}
// ======================================
// public function
// ======================================
private function itemChanged():void
{
isNeedRefresh = true;
isValueChanged = true;
checkValidity();
}
// ======================================
// properties
// ======================================
private var _required:Boolean = false;
private var _validity:Boolean = false;
private var _defaultItemIndex:int = 0;
public function get required():Boolean
{
return _required;
}
[Inspectable(defaultValue=false, category="Other")]
public function set required(value:Boolean):void
{
_required = value;
isNeedRefresh = true;
checkValidity();
}
[Bindable("PLControlComboboxChanged")]
public function get controlValue():Object
{
return this.selectedIndex;
}
public function set controlValue(value:Object):void
{
if(value is Number)
{
this.selectedIndex = int(value);
itemChanged();
}
}
/**
* #copy IPLControlControl#validity
*/
public function get validity():Boolean
{
return _validity;
}
/**
* #copy IPLControlControl#type
*/
public function get type():String
{
return PLControlTypeList.CONTROL_TYPE_COMBOBOX;
}
/**
* If required is true, the default Item can not be selected.
*/
public function get defaultItemIndex():int
{
return _defaultItemIndex;
}
[Inspectable(defaultValue=0, type="Number", category="Other")]
public function set defaultItemIndex(index:int):void
{
_defaultItemIndex = index;
isNeedRefresh = true;
checkValidity();
}
/**
* Override for check validity.
*/
override public function set selectedIndex(value:int):void
{
super.selectedIndex = value;
itemChanged();
}
/**
* Override for check validity.
*/
override public function set selectedItem(value:Object):void
{
super.selectedItem = value;
itemChanged();
}
}
}
Its coming from mx.controls.Comboxbox line # 1681 because tween is null.
private function destroyDropdown():void
{
if (inTween)
tween.endTween();//<---- exception on this line
displayDropdown(false, null, false);
}
Any suggestions of why this could be happening?
Issue fixed in Apache Flex 4.10 and above, see https://issues.apache.org/jira/browse/FLEX-33382.
If using an older SDK you could monkey patch mx:ComboBox like so adding the "&& tween" check:
private function destroyDropdown():void
{
if (inTween && tween)
tween.endTween();
displayDropdown(false, null, false);
}
i want to call an external function inside a class. thats the code;
in checkConnectionStatus function,
this[_funcNameForSucceededCon].apply(); doesnt work because "this" is the class, not the Application. How can i reach Application at this time or what can i do?
any help will be greatly appreciated.
best regards,
mira.
package myLibrary
{
import air.net.URLMonitor;
import flash.events.Event;
import flash.events.StatusEvent;
import flash.net.URLRequest;
public class connectionControl
{
private var _urlReq:URLRequest;
private var _urlMonitor:URLMonitor;
private var _funcNameForSucceededCon:String;
private var _funcNameForFailedCon:String;
public function connectionControl(targetURL:String, funcNameForSucceededCon:String, funcNameForFailedCon:String)
{
_urlReq = new URLRequest(targetURL);
_urlMonitor = new URLMoniotor(_urlReq);
_urlMonitor.addEventListener(StatusEvent.STATUS, checkConnectionStatus);
_funcNameForSucceededCon = funcNameForSucceededCon;
_funcNameForFailedCon = funcNameForFailedCon;
if(_urlMonitor.running == false)
{
_urlMonitor.start();
}
else
{
_urlMonitor.stop();
_urlMonitor.start();
}
}
private function checkConnectionStatus(e:Event):void
{
_urlMonitor.removeEventListener(StatusEvent.STATUS, checkConnectionStatus);
if(_urlMonitor.available)
{
this[_funcNameForSucceededCon].apply();
}
else
{
this[_funcNameForFailedCon].apply();
}
}
}
}
You have passed the name of the function to be serving as a callback. Use instead the function itself and pass it to connectionControl.
public class connectionControl
{
private var _funcSucceededCon:Function;
private var _funcFailedCon:Function;
public function connectionControl(targetURL:String, funcSucceededCon:Function, funcFailedCon:Function)
{
_urlReq = new URLRequest(targetURL);
_urlMonitor = new URLMoniotor(_urlReq);
_urlMonitor.addEventListener(StatusEvent.STATUS, checkConnectionStatus);
_funcSucceededCon= funcSucceededCon;
_funcFailedCon= funcFailedCon;
...
And:
if(_urlMonitor.available)
{
_funcSucceededCon();
}
I am trying to make a class that staggers the net connections calls by a certain amount to not put too much pressure on my server, and so I don't have a dozen net connectors running around in my code.
I want a class that I can send a call command to, the class adds the call to the queue, and then about every one second it see if anything is in the queue, and if so calls it. This is what I have so far.
package net
{
import flash.events.TimerEvent;
import flash.net.NetConnection;
import flash.net.Responder;
import flash.utils.Timer;
public class Server
{
private static var gateway:String = "http://localhost/gateway.php";
private static var queue:Vector.<ServerNode>
private static var nc:NetConnection;
private static var instance:Server = null;
private static var res:Responder;
private var timer:Timer;
public function Server(e:ServerEnforcer) {
nc = new NetConnection();
queue = new Vector.<ServerNode>();
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, execCall);
timer.start();
}
public static function getInstance():Server {
if (instance == null) {
instance = new Server(new ServerEnforcer);
}
return instance;
}
private function execCall(e:Event):void {
if (queue.length > 0) {
var node:ServerNode = queue.pop();
nc.call(node.method, node.res, node.args);
}
}
public function call(method:String, success:Function, failure:Function, ...args):void {
queue.unshift(new ServerNode(method, success, failure, args));
}
private function serverFailure(event:Object):void {
trace("Server Failure : " + event.description);
}
}
}
import flash.net.Responder;
class ServerEnforcer { }
class ServerNode {
public var method:String;
public var success:Function;
public var failure:Function;
public var args:Array;
public var res:Responder
public function ServerNode(_method:String, _success:Function, _failure:Function, _args:Array) {
method = _method;
success = _success;
failure = _failure;
res = new Responder(success, failure);
args = _args;
}
}
Now when I call
Server.getInstance().call("Fetch.getData", parseAllData, onError)
public function parseAllData(event:Object):void {
trace("Victory!");
}
public function onError(event:Object):void {
trace("Error :" + event);
}
absolutely nothing happens. Any idea why or a point in the right direction why this isn't working?
You created an instance of the NetConnection, but haven't actually initiated a connection with the server.
In other words,
nc.connect(gateway);
is missing.
See NetConnection documentation for more information on that class.
I know there is something I am doing wrong. In my controls I have keydown events that control my hero. As of right now, I am trying to rotate my hero but he refuses to turn . Below is my Hero Class, my control class, and gameobject class. pretty much all the classes associate with the controls class.
package com.Objects
{
import com.Objects.GameObject;
/**
* ...
* #author Anthony Gordon
*/
[Embed(source='../../../bin/Assets.swf', symbol='OuterRim')]
public class Hero extends GameObject
{
public function Hero()
{
}
}
}
Here is my Controls class. This is the class where I am trying to rotate my hero but he doesnt. The keydown event does work cause I trace it.
package com.Objects
{
import com.Objects.Hero;
import flash.events.*;
import flash.display.MovieClip;
/**
* ...
* #author Anthony Gordon
*/
public class Controls extends GameObject
{
private var aKeyPress:Array;
public var ship:Hero;
public function Controls(ship:Hero)
{
this.ship = ship;
IsDisplay = false;
aKeyPress = new Array();
engine.sr.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
engine.sr.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
}
private function keyDownListener(e:KeyboardEvent):void {
//trace("down e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode] = true;
trace(e.keyCode);
}
private function keyUpListener(e:KeyboardEvent):void {
//trace("up e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=false;
}
override public function UpdateObject():void
{
Update();
}
private function Update():void
{
if (aKeyPress[37])//Key press left
ship.rotation += 3,trace(ship.rotation ); ///DOESNT ROtate
}//End Controls
}
}
Here is GameObject Class
package com.Objects
{
import com.Objects.Engine;
import com.Objects.IGameObject;
import flash.display.MovieClip;
/**
* ...
* #author Anthony Gordon
*/
public class GameObject extends MovieClip implements IGameObject
{
private var isdisplay:Boolean = true;
private var garbage:Boolean;
public static var engine:Engine;
public var layer:Number = 0;
public function GameObject()
{
}
public function UpdateObject():void
{
}
public function GarbageCollection():void
{
}
public function set Garbage(garb:Boolean):void
{
garbage = garb;
}
public function get Garbage():Boolean
{
return garbage
}
public function get IsDisplay():Boolean
{
return isdisplay;
}
public function set IsDisplay(display:Boolean):void
{
isdisplay = display;
}
public function set Layer(l:Number):void
{
layer = l;
}
public function get Layer():Number
{
return layer
}
}
}
Looks like your keyUpListener and keyDownListener methods aren't calling the UpdateObject function.
Try listening for your KeyboardEvent on stage instead of engine.sr (not sure what that is)
If you put them on anything other than the stage you will need to click that specific thing first to give it focus for the events to work.
Also, the line:
ship.rotation += 3,trace(ship.rotation );
in your Control class looks a bit broken.
I have a collection of objects and each object throws an event every time its value gets updated. Im trying to capture that event by adding a listener to the arraycollection that holds it (see main class) but its not working. Honestly I'm not sure this is the correct approach.
I'm avoiding using Collection.CHANGE because it fells into an infinite recursion ultimately ends in a stack overflow. Any ideas?
[Bindable]
public class NamesVO {
public var steveList:ArrayCollection; // array of SteveVO objects
public function NamesVO() {
steveList = new ArrayCollection();
}
public function rename():void {
for each(var steve:SteveVO in steveList) {
steve.rename();
}
}
}
[Bindable]
public class SteveVO extends EventDispatcher {
public static const VALUE_CHANGED:String = "VALUE_CHANGED";
public var code:String;
public var name:String;
public var _quantity:Number;
public function SteveVO() {
this.code = "";
this.name = "";
_quantity = 0;
}
public function get quantity():Number {
return _quantity;
}
public function set quantity(quantity:Number):void {
_quantity = quantity;
dispatchEvent(new Event(VALUE_CHANGED));
}
public function rename():void {
name = code + " - " + _quantity;
}
}
Main class:
names = new NamesVO();
names.steveList.addEventListener(SteveVO.VALUE_CHANGED, function():void {
names.rename(); // this anon function is not being executed!!
});
var steve:SteveVO = new SteveVO();
names.steveList.addItem(steve);
// names is bound on a datagrid and uses itemeditor for each SteveVO object
The VALUE_CHANGED event is not dispatched by the steveList array Collection so won't be detected by your listener. You could encapsulate the functionality you want inside the NamesVO class by detecting when an item is added to the array collection and adding a listener to the new steveVO object that dispatches the same event from NamesVO. Then just listen for that event in your main class.
Is there a reason to change all the names when one quantity is changed. Would it be better simply to call rename inside the set function of the steveVO class?
To implement the change:
import flash.events.Event;
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
[Bindable]
public class namesVO
{
public var steveList:ArrayCollection; // array of SteveVO objects
public function namesVO()
{
steveList = new ArrayCollection();
steveList.addEventListener(CollectionEvent.COLLECTION_CHANGE,collChanged);
}
private function collChanged(e:CollectionEvent):void
{
if (e.kind == CollectionEventKind.ADD)
e.items[0].addEventListener(steveVO.VALUE_CHANGED,valueChanged);
}
private function valueChanged(e:Event):void
{
dispatchEvent(new Event(steveVO.VALUE_CHANGED));
}
public function rename():void
{
for each(var steve:steveVO in steveList)
{
steve.rename();
}
}
}
In the main class use:
names = new namesVO();
names.addEventListener(steveVO.VALUE_CHANGED, function():void
{
names.rename();
});
steve = new steveVO();
names.steveList.addItem(steve);
steve.quantity = 12;
Of course this is only an example and only includes the case where one item is added at a time.