PDA

Volledige versie bekijken : Private var werkt niet?


PageMaker
%Europe/Berlin %663 %2010, 15:56
Ik heb - onder meer - de volgende code:

private var largeHoog:uint;
private var largeWide:uint;

private var loader:Loader = new Loader();
private var largeImage:Bitmap;
..........
private function loadLargeImage( imageURL:String ):void
{
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, storeLargeImage );
loader.load( new URLRequest( imageURL ));
}

private function storeLargeImage( $evt:Event ):void
{
largeImage = Bitmap( loader.content );
largeHoog = largeImage.height;
largeWide = largeImage.width;
// trace("largeHoog: " + largeHoog); // output: 500
} // storeLargeImage

private function getFotoPosAndProps( textBox:TextField ):void
{
textBox.appendText( "largeHoog: " + largeHoog + " largeWide: " + largeWide + "\n");
} // getFotoPosAndProps
In "getPosAndProps" krijg ik voor largeHoog en LargeWide steeds 0 terwijl in de trace gewoon de hoogte van de foto staat; ziet iemand iets dat ik (nu) niet meer zie?

O ja, ik roep getFotoPosAndProps aan NA loadLargeImage.

PsK
%Europe/Berlin %670 %2010, 16:06
Hoi PageMaker,

Waarschijnlijk komt het omdat je getFotoPosAndProps() al aanroept voordat je plaatje is geladen dus voordat storeLargeImage() word aangeroepen door je eventListener.
Ik weet verder niet hoe je code in elkaar steekt, maar je moet ervoor zorgen dat getFotoPosAndProps() na storeLargeImage() word aangeroepen en niet alleen na loadLargeImage().

succes :)

PageMaker
%Europe/Berlin %678 %2010, 16:17
Lijkt me eerlijk gezegd ook de enige logische verklaring, maar:
1. Dat COMPLETE event zorgt er toch voor dat "storeLargeImage" pas wordt uitgevoerd als het laden gereed is.
2. Bovendien de trace in "storeLargeImage" zegt dat largeHoog een waarde heeft.
3. Daarnaast: wanneer ik in "storeLargeImage" addChild( largeImage ) opneem, dan verschijnt heel braaf de betreffende foto.
Ik begrijp het dan ook nog steeds niet.

Dauntless
%Europe/Berlin %759 %2010, 18:13
storeLargeImage wordt wel opgeroepen nadat het laden compleet is, maar daarom getFotoPosAndProps nog niet. Hoe & waar roep je getFotoPosAndProps op?

Jan
%Europe/Berlin %761 %2010, 18:16
Toon het script waar (en vooral wanneer) je getFotoPosAndProps(tf); hebt.

Jan

PageMaker
%Europe/Berlin %792 %2010, 19:00
Dis is de betreffende klasse:
package
{
import flash.display.Sprite;
import flash.display.Loader; // > DisplayObjectContainer > InteractiveObject > DisplayObject
import flash.display.Bitmap; // > DisplayObject > EventDispatcher > Object
import flash.events.Event; // > Object
import flash.net.URLRequest; // > Object
import flash.system.Capabilities; // > Object

import flash.text.TextField;

public class ViewImage extends Sprite
{
private var screenH:uint;
private var screenW:uint;

private var maxFotoH:uint;
private var maxFotoW:uint;

private var largeHoog:uint;
private var largeWide:uint;

private var largeImage:Bitmap;

private static const BORDER_SIZE = 30;

public function ViewImage( imageURL:String, textBox:TextField ):void
{
textBox.appendText( "ViewImage.imageURL: " + imageURL + "\n");

getScreenPosAndProps();

textBox.appendText( "ViewImage.screenH: " + screenH + "\n");
textBox.appendText( "ViewImage.screenW: " + screenW + "\n");

loadLargeImage( imageURL );

getFotoPosAndProps( textBox );


} // constructor

private function getScreenPosAndProps():void
{
screenH = Capabilities.screenResolutionY;
screenW = Capabilities.screenResolutionX;

maxFotoH = screenH - 2 * BORDER_SIZE;
maxFotoW = screenW - 2 * BORDER_SIZE;
} // getScreenPosAndProps

private function loadLargeImage( imageURL:String ):void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, storeLargeImage );
loader.load( new URLRequest( imageURL ));
}

private function storeLargeImage( $evt:Event ):void
{
largeImage = Bitmap( $evt.target.content );

//largeImage = $evt.target.content as Bitmap;

trace("largeImage.width: " + largeImage.width + "\n");
} // storeLargeImage

private function getFotoPosAndProps( textBox):void
{
textBox.appendText( "largeHoog: " + largeImage.height + " largeWide: " + largeImage.width + "\n");

} // getFotoPosAndProps

} // class ViewImage
} // packageDit:
trace("largeImage.width: " + largeImage.width + "\n");geeft een voortreffelijke output.
En op dit statement:
textBox.appendText( "largeHoog: " + largeImage.height + " largeWide: " + largeImage.width + "\n");volgt de volgende foutmelding:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at ViewImage/::getFotoPosAndProps()
at ViewImage$iinit()
at Main/::imagePassHandler()
at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunctio n()
at flash.events::EventDispatcher/dispatchEvent()
at ClickButton/::fotoClickHandler()
largeImage.width: 700En omdat de foutmelding eerder wordt getoond dan de trace output, vermoed ik dat "getFotoPosAndProps" toch eerder wordt uitgevoerd dan de completehandler. largeImage.height etc bestaat blijkbaar nog niet.
Hoe dwing ik dat ding nu om het in de door mij gewenste (geeiste) volgorde te doen?

Dauntless
%Europe/Berlin %807 %2010, 19:22
loadLargeImage( imageURL );

getFotoPosAndProps( textBox );
Je wacht dus niet tot de foto klaar is met laden. Dispatch een event wanneer loadLargeImage klaar is en pas vanaf DAN kan je de getFotoPosAndProps opvragen.

(Of aangezien het in dezelfde classe is, roep gewoon getFotoPosAndProps aan vanuit de Complete van je image)

PageMaker
%Europe/Berlin %915 %2010, 21:57
Ok, wat je zegt zou in dit geval kunnen.
Maar stel nu eens het geval dat ik die "get FotoPosAndProps" niet in dezelfde functie wil hebben; hoe doe ik het dan?

Dauntless
%Europe/Berlin %085 %2010, 02:03
Door een nieuw event te dispatchen wanneer je klaar bent en daar naar te luisteren. Of door gewoon een 2de Event.COMPLETE listener toe te voegen.

PageMaker
%Europe/Berlin %638 %2010, 15:19
Dank je, ik begrijp wat je bedoelt.
Maar......... wanneer een COMPLETE listener nu zegt "He, ik ben gereed" dan heb ik toch niet nog zo'n zelfde listener nodig die zegt: "He, de complete listener heeft gezegd dat ie gereed is".
Anders gezegd: complete is toch complete, of ontgaat mij hier een essentie?
Nog weer anders: ik vind het een beetje dubbel-op-is-eens-zo-dik.

Dauntless
%Europe/Berlin %727 %2010, 17:27
Maar je zegt net dat je die functie aanroep niet in de storeLargeImage wil zetten, terwijl hij pas vanaf dan opgeroepen kan worden.

PageMaker
%Europe/Berlin %752 %2010, 18:02
OK, het is dus de handler van de handler die gereed moet zijn.
Anders gezegd: ik moet in "storeLargeImage" ( de loadCompleteHandler ) een event afvuren dat zegt dat deze handler gereed is en daarna m'n functie getFotoPosAndProps uitvoeren.

Dauntless
%Europe/Berlin %784 %2010, 18:49
Bv ja. Maar ik denk dat je toch 'the bigger picture' inderdaad niet hebt.

Wat je nu hebt is dit:
var object:Object;
var mc:MovieClip = new MovieClip();
this.addChild(mc);

trace(object); //null
mc.addEventListener(MouseEvent.CLICK, onClick);

function onClick(e:Event)
{
object = new Object();
}
}(Uiteraard is de MC niet klikbaar omdat hij leeg is, maar daar gaat het niet om) Het klikken is hier gelijk aan het voltooien van het inladen.

Natuurlijk moet je dus wachten met object te tracen tot de onClick wel degelijk uitgevoerd is.

PageMaker
%Europe/Berlin %529 %2010, 12:41
Mijns inziens heb ik met onderstaande (gestripte versie) code je aanwijzingen gevolgd; maar.... de foutmeldingen staan in de code. Hoe kom ik daar nu weer langs?
package
{
import flash.display.Sprite;
import flash.display.Loader; // > DisplayObjectContainer > InteractiveObject > DisplayObject
import flash.display.Bitmap; // > DisplayObject > EventDispatcher > Object
import flash.events.Event; // > Object
import flash.net.URLRequest; // > Object

import flash.text.TextField;

public class ViewImage extends Sprite
{
private var largeHoog:uint;
private var largeWide:uint;

private var loader:Loader = new Loader();

private var largeImage:Bitmap;

public function ViewImage( imageURL:String, textBox:TextField ):void
{
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));

getFotoPosAndProps( textBox );
} // constructor

private function onComplete( $evt:Event ):void
{
//largeImage = new Bitmap( loader.content ); // dit geeft foutmelding:
// 1067: Implicit coercion of a value of type flash.display:DisplayObject
// to an unrelated type flash.display:BitmapData.

largeImage = new Bitmap( $evt.target.content ); // en dit geeft:
// TypeError: Error #1034: Type Coercion failed: cannot convert
// flash.display::Bitmap@3a4aef9 to flash.display.BitmapData.
// at ViewImage/::onComplete()

largeHoog = largeImage.height;
} // largeImageHandler

private function getFotoPosAndProps( textBox:TextField ):void
{
textBox.appendText( "largeHoog: " + largeHoog + "\n");

} // getFotoPosAndProps

} // class ViewImage
} // package

Jan
%Europe/Berlin %530 %2010, 12:44
public function ViewImage( imageURL:String, textBox:TextField ):void
{
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));
getFotoPosAndProps( textBox );//deze functie wordt uitgevoerd 1 milliseconde na de vorige regel waarop je load deed.
//De laadoperatie is dan nog lang niet gedaan en dus is die largeHoog op dit moment nog altijd undefined.
}
largeImage = new Bitmap( $evt.target.content );
largeImage = $evt.target.content as Bitmap;
of
largeImage = Bitmap($evt.target.content);
Je moet het casten naar een bepaald type, je moet geen nieuwe Bitmap aanmaken want je content is al een bitmap.
Het is new Bitmap(bitmapdata) maar jij doet new Bitmap(bitmap)

Laat ook die $ achterwege...

Jan

PageMaker
%Europe/Berlin %544 %2010, 13:03
Dankje, Jan; dat schiet weer een stuk in de goede richting.
Ik heb nu deze code, maar het "vullen" van de private var largeHoog wil nog niet echt lukken.
In de onComplete handler gaat het prima, maar daarna bij het aanroepen van getFotoPosAndProps lijkt ie het noorden weer wat verloren te hebben.
Wat kan ik daar aan doen?
private function onComplete( evt:Event ):void
{
largeImage = evt.target.content as Bitmap;
largeHoog = largeImage.height;

trace("onComplete.largeHoog: " + largeHoog + "\n");
} // largeImageHandler

private function getFotoPosAndProps( textBox:TextField ):void
{
trace( "getFotoPosAndProps.largeHoog: " + largeHoog + "\n");
// output:
// op de eerste plaats: getFotoPosAndProps.largeHoog: 0
// op de tweede plaats: onComplete.largeHoog: 500
} // getFotoPosAndProps

Jan
%Europe/Berlin %556 %2010, 13:22
Het is toch zonneklaar dat je getFotoPosAndProps niet kan aanroepen voordat de laadoperatie helemaal gedaan is, want je gebruikt 'dingen' in die getFotoPosAndProps functie die pas bekend/ingevuld zijn in de onComplete functie.

//Main.as
var tf:TextField=new TextField();
var viewImg :ViewImage = new ImageView('images/img1.jpg', tf);
//en jij wil dat er dan automatisch die eigenschappen van img1.jpg in dat textfield hier komen te staan.

//ViewImage.as
public class ViewImage extends Sprite
{
private var largeHoog:uint;
private var largeWide:uint;
private var loader:Loader = new Loader();
private var largeImage:Bitmap;
private var tf:TextField
public function ViewImage( imageURL:String, textBox:TextField ):void
{
this.tf = textBox;
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));
}
private function onComplete( event:Event ):void
{
largeImage = Bitmap( loader.content);
largeHoog = largeImage.height;
tf.appendText( "largeHoog: " + largeHoog + "\n");
}

}
OF met een event:

//Main.as
var tf:TextField=new TextField();
var viewImg:ViewImage = new ViewImage ('images/img1.jpg');
imgView.addEventListener('ready', onImgViewReady)
function onImgViewReady(event:Event)
{
var img = event.currentTarget as ViewImage ;
tf.appendText( "largeHoog: " + img.largeHoog + "\n");
}

//ViewImage.as
public class ViewImage extends Sprite
{
public var largeHoog:uint;
public var largeWide:uint;
private var loader:Loader = new Loader();
private var largeImage:Bitmap;

public function ViewImage( imageURL:String):void
{
this.tf = textBox;
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));
}
private function onComplete( event:Event ):void
{
largeImage = Bitmap( loader.content);
largeHoog = largeImage.height;
largeWide = largeImage.width;
dispatchEvent(new Event('ready'));//je kan ook gewoon het complete event door dispatchen...
}
}
Jan

PageMaker
%Europe/Berlin %596 %2010, 14:18
Jan je zegt:
Het is toch zonneklaar dat je getFotoPosAndProps niet kan aanroepen voordat de laadoperatie helemaal gedaan isDat is het, daar bestaat geen misverstand over.

Wanneer ik nu doe:
private function onComplete( evt:Event ):void
{
largeImage = evt.target.content as Bitmap;
} // largeImageHandlerDan verwacht ik dat de private variabele "largeImage" binnen de klasse ViewImage is gevuld met die bitmap als de onCompleet klaar is; en dat is ie op het moment dat ie die variabele heeft gevuld want dat is het enige dat ie na het laden van dat plaatje moet doen.
Wanneer ik nu in de onCompleet handler een functie opneem dan verleg ik het probleem alleen maar; ik heb dan nog steeds niet op klasse niveau de inhoud van largeImage te pakken die blijft immers alleen maar binnen die nieuwe functie bestaan.
Als ik m'n vraag op een andere manier stel: "Hoe krijg ik de inhoud van die geladen bitmap op klasse niveau beschikbaar in de private variabele largeImage zodat ik de eigenschappen van dat plaatje in een aantal andere functies binnen dezelfde klasse kan gebruiken".
En vergeet dat textfield, dat is alleen maar bedoeld om de zaak zichtbaar te maken in plaats van een trace.

Jan
%Europe/Berlin %606 %2010, 14:34
"Hoe krijg ik de inhoud van die geladen bitmap op klasse niveau beschikbaar in de private variabele largeImage zodat ik de eigenschappen van dat plaatje in een aantal andere functies binnen dezelfde klasse kan gebruiken".
Zoals het er nu staat. Maar je moet largeImage niet gebruiken voordat die 'gevuld' is.

Misschien heb je niet door/begrepen dat Flash niet wacht met het uitvoeren van de volgende regel. Hij voert ze allemaal achter elkaar uit. Dat daar een load() operatie tussenstaat maakt geen verschil. Hij gaat toch niet wachten totdat de load complete is voordat ie de volgende regel script gaat uitvoeren. :S

var nr:int=10;
setTimeout(changeNr,1000);
trace(nr);//10 (hij wacht toch niet op changeNr() voordat ie deze trace doet... idem voor load()
function changeNr()
{
nr=11;
}

Jan

PageMaker
%Europe/Berlin %639 %2010, 15:20
Misschien heb je niet door/begrepen dat Flash niet wacht met het uitvoeren van de volgende regel. Hij voert ze allemaal achter elkaar uit. Dat daar een load() operatie tussenstaat maakt geen verschil. Hij gaat toch niet wachten totdat de load complete is voordat ie de volgende regel script gaat uitvoerenJa, inderdaad daar heb ik geen rekening mee gehouden - eigenwijs ding trouwens, enig idee waarom dat zo is gemaakt?

Maar terug naar het onderwerp.
Hoe dwing ik Flash dan te wachten totdat de onComplete geheel is uitgevoerd voordat ie aan een nieuw statement begint; een timer werkt niet dat heb je al laten zien. Daar moet vast een oplossing voor zijn want ik ben stellig niet de enige die tegen dat probleem aan loopt.
Ik wil gewoon dit doen:
public function ViewImage( imageURL:String, textBox:TextField ):void
{
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));

getFotoPosAndProps( largeImage );
} // constructor

private function onComplete( evt:Event ):void
{
largeImage = evt.target.content as Bitmap;
} // onComplete
en wanneer dat echt niet gaat, dan moet ik wat anders verzinnen.
Wat ik nog kan bedenken is een timer en dan herhaaldelijk checken of largeImage nog steeds nil is.

PageMaker
%Europe/Berlin %698 %2010, 16:46
Het had wat voeten in de aarde, maar dit werkt!
private var loader:Loader = new Loader();

public function ViewImage( imageURL:String, textBox:TextField ):void
{
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));

var flashReady:Boolean = isFlashReady();
if( flashReady )
{
getFotoPosAndProps( largeImage );
} else {
var readyTimer:Timer = new Timer( 100 );
readyTimer.addEventListener( TimerEvent.TIMER, onTimer );
readyTimer.start();
} // if-else
} // constructor

private function onComplete( evt:Event ):void
{
largeImage = evt.target.content as Bitmap;
} // onComplete

private function isFlashReady():Boolean
{
var result:Boolean = (largeImage != null );
return result
} // isFlashReady

private function onTimer( evt:TimerEvent ):void
{
var isReady:Boolean = isFlashReady();
if( isReady )
{
Timer( evt.target ).stop();
getFotoPosAndProps( largeImage );
} // if
} // onTimer

private function getFotoPosAndProps( largeImage:Bitmap ):void
{
largeHoog = largeImage.height;
trace("getFotoPosAndProps.largeHoog: " + largeHoog + "\n");

this.addChild( largeImage );
} // getFotoPosAndProps

Iedereen zeer bedankt voor de les!!

jaspermuts
%Europe/Berlin %700 %2010, 16:49
Hoe dwing ik Flash dan te wachten totdat de onComplete geheel is uitgevoerd voordat ie aan een nieuw statement begint
Lees nu je dit doorhebt nog eens dit hele topic door, Dauntless en Adnez proberen je juist de hele tijd precies uit te leggen hoe je dat doet (middels events dus). Zie vooral posts #7 en #9

Dauntless
%Europe/Berlin %772 %2010, 18:32
En voor de volledigheid: Het is NIET mogelijk om gewoon te 'wachten' met een statement.

Ja, inderdaad daar heb ik geen rekening mee gehouden - eigenwijs ding trouwens, enig idee waarom dat zo is gemaakt?
AS is een asynchrone programmeer taal (werkt met events) en zo is het nu eenmaal.
Beeld je eens in dat dat niet zo is: Probeer dan maar eens een preloader te maken. Dat gaat natuurlijk niet aangezien je NIETS anders kan doen tot de foto geladen is. Je kan grafisch niets updaten. Dit gaat nu over een Loader, maar zoals ik aantoonde werkt het klikken op een knop net hetzelfde:
var object:Object;
var mc:MovieClip = new MovieClip();
this.addChild(mc);

addButtonListener();

trace("Klaar");
function addButtonListener()
{

mc.addEventListener(MouseEvent.CLICK, onClick);

}
function onClick(e:Event)
{
object = new Object();
}
}Volgens jou logica mag "Klaar" pas uitgevoerd worden wanneer er op de button gedrukt is. (Ga maar na, het is EXACT hetzelfde principe)

PageMaker
%Europe/Berlin %666 %2010, 16:00
Na een nachtje slapen en nog eens goed nalezen wat er allemaal is gezegd, moet ik zeggen dat ik wel erg moeilijk ben bezig geweest. Het kan allemaal een stuk eenvoudiger. Maar ja, beter laat dan nooit; en van achteren kijk je een koei in z'n ........ zeggen ze in Zeeland.
Ik heb nu dit:
// ViewImageSimplet.as
package
{
import flash.display.Sprite;
import flash.display.Loader; // > DisplayObjectContainer > InteractiveObject > DisplayObject
import flash.display.Bitmap; // > DisplayObject > EventDispatcher > Object
import flash.events.Event; // > Object
import flash.net.URLRequest; // > Object
import flash.text.TextField;

public class ViewImage extends Sprite
{
private var textBox:TextField;
private var largeImage:Bitmap;
private var largeHoog:uint;
private var largeWide:uint;
private var loader:Loader = new Loader();

public function ViewImage( imageURL:String, myBox:TextField ):void
{
this.textBox = myBox;
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
loader.load( new URLRequest( 'images/img1.jpg' ));
} // constructor

private function onComplete( evt:Event ):void
{
largeImage = evt.target.content as Bitmap;
getFotoPosAndProps( textBox )
} // onComplete

private function getFotoPosAndProps( textBox:TextField ):void
{
largeHoog = largeImage.height;
textBox.appendText("getFotoPosAndProps.largeHoog: " + largeHoog + "\n");
this.addChild( largeImage );
} // getFotoPosAndProps

} // class ViewImage
} // packageen dat werkt als een tierelier.
Nogmaals iedereen bedankt voor de les en het geduld.