Flex: Change text value with loop and make image from every changed value? - actionscript-3

I want to change taxt value from loop and every time I have changed it I take image from that.
I have two numeric steppers where other is start number and other is end number. I have also button that starts function.
So after pressed it starts:
private function makeFrames():void
{
for (var i:int = 0; i < endFrameNumber.value; i++)
{
currentFrameNumber++;
frameText.text = currentFrameNumber.toString();
makeImage(currentFrameNumber);
}
}
Then I make image from text:
private function makeImage(value:int):void
{
var projectFolderName:String = createFolder();
bitmapData = new BitmapData(frameText.width,frameText.height, true, 0x00ffffff);
bitmapData.draw(frameText,new Matrix());
var bitmap : Bitmap = new Bitmap(bitmapData);
var png:PNGEncoder = new PNGEncoder();
var ba:ByteArray = png.encode(bitmapData);
newImage = File.desktopDirectory.resolvePath(projectFolderName + "/" + "frame-number_" + value + ".png");
fileStream = new FileStream();
fileStream.open(newImage, FileMode.APPEND);
fileStream.writeBytes(ba);
fileStream.close();
}
So first I change text value and then I try to capture it. It make images yes, but all numbers is same. So how I can make it to change text value every time when I run "makeImage" in loop and it captures all images between start and end numbers??
Using Flash Builder 4.6 and AIR.

You should read about Flex Components Lifecycle.
So, there are two way to solve your problem:
Using invalidateProperties -> commitProperties.
addEventListener on Event.ENTER_FRAME
Sure you can't use foreach. In each enter frame you should:
Set new text
Invalidate text display
Make and save image

Related

How do I get images to update dynamically with a slider in actionscript 3?

Here is my dilemma. We use image stacks a lot here with alpha channels. I want to call up images in series using a slider. I am getting a concatenated string a pull up an image from my folder. But I can not get the images to load dynamically when I slide the slider bar.
I am using the frame number to change the file name to pull up the next frame. I can get the image to show up if I put the loader outside of the function, but when I put the loader in the function I get error after error saying the file cannot be located.
Here is the code as it currently stands :
var imgLoader = new Loader();
var str1 = String (".jpg");
var sliderValue:uint = mySlider.sliderKnob.x / 3;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(event:Event):void {
sliderValue = mySlider.sliderKnob.x / 3;
status_txt.text = "Slider position is: "+sliderValue;
fileText.text = "Sketch_0"+sliderValue+".jpg";
imgLoader.load( new URLRequest ( "Sketch_0"+sliderValue+".jpg"));
addChild(imgLoader);
setChildIndex(imgLoader, 0);
}
First thing up, you need to load one image without that slider stuff and see if it loads. Verify the paths if not. Relative paths, as you put them, will work relatively to the folder where SWF is (or where the HTML page, containing the SWF, is).
Second, relieve the heavy burden you are trying to put on the Flash Player.
addEventListener(Event.ENTER_FRAME, onFrame);
var nextName:String;
function onFrame(e:Event):void
{
var anIndex:int = mySlider.sliderKnob.x / 3;
var aName:String = "Sketch_0" + anIndex + ".jpg";
status_txt.text = "Slider position is: " + anIndex;
fileText.text = aName;
// Flash Player does not load images instantly,
// so lets request new image only if user stopped moving the slider.
if (aName == nextName)
{
loadNext(nextName);
}
else
{
nextName = aName;
}
}
var currentName:String;
var currentImage:Loader;
function loadNext(value:String):void
{
// If the requested file is the same as current, just ignore the request.
if (value == currentName) return;
currentName = value;
// Dispose of the previous image in a proper way.
if (currentImage)
{
removeChild(currentImage);
currentImage.unloadAndStop(true);
currentImage = null;
}
// Create a new one.
var aRequest:URLRequest = new URLRequest(currentName);
currentImage = new Loader();
currentImage.load(aRequest);
addChild(currentImage);
}

How to convert different line of a dynamic text box to Movie clip in AS3

I have a question regarding to my project which is How to convert different line of a dynamic text box to Movie clip in AS3?
Actually, I have an text file named test.txt. For instance:
It consists of:
today is Sun;
today is Mon;
today is Tue;
today is Wed;
today is Thu;
today is Fri;
today is Sat;
and then I want to put all of them into an array and then a string to show them in the dynamic text Box called text_txt.
I have different objects in my library. If we see "sun" in the first line, the first object (obj01) will be shown in a specific area which is inside a movie clip called mc.
The question is here:
Fist: if I have different texts in my first line. for instance "today is sun;". how to find that the "sun" is in this line???
Second: How to convert different line of a dynamic text box to Movie clip. So, if user click on the "obj01", the first line in the dynamic textbox will become bigger???
Thanks for your time and help in advance.
import flash.events.MouseEvent;
var flag:int = 0;
//load the txt file
var myTextLoader:URLLoader = new URLLoader();
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);
myTextLoader.load(new URLRequest("test.txt"));
//when the scene loads, all the info from txt file shown into the dynamic text;
function onLoaded(e:Event):void
{
//put all the info into array
var days:Array = e.target.data.split(/\n/);
var str:String;
//show them in the dynamic text
for (var i=0; i<days.length; i++)
{
str = days[i];
text_txt.appendText(str + "\n");
//if one text founded, do somethind and shoe an objectinthe output;
switch (str)
{
case "sun;\r" :
var obj01:Show = new Show();
mc.addChild(obj01);
obj01.x = -200;
obj01.y = -15;
break;
default :
trace("None of the above were met");
}
}
obj01.buttonMode = true;
//if the object clicked then something must be happend to the first line in the dynamic text box
obj01.addEventListener(MouseEvent.CLICK, firstLine);
function firstLine(e:MouseEvent):void
{
flag = 1;
switch (flag)
{
case 1 :
trace("Clicked!");
//the first line in the text box should get a different background and become more bigger
//Do I need to convert the first line to a movieclip? OR I need to do in another way?!
break;
default :
trace("None");
}
}
}
First: if I have different texts in my first line. for instance "today
is sun;". how to find that the "sun" is in this line???
split whole of the dynamic-text value with its lines to an Array
then check each array item if contains that key ("sun").
you have to use some thing like it Array[x].indexOf(key) >= 0
Second: How to convert different line of a dynamic text box to Movie
clip. So, is user click on the "mc.obj01", the first line in the
dynamic textbox will become bigger???
i just give you an example to find the reason of difference in size of movieclip and text-display. this image comes from adobe-flash. a text field with its value "brown fox jumps" has the same size as the green rectangle. but the text-size shown by the red rectangle.
Green is textfield size, same as textField.width & textField.height
Red is text size, same as textField.textWidth & textField.textHeight
so you must resize your movieclip/textfield to second Values(Red);
my answer is not walkthrough but a guidance.
After too much research and try a lot of functions, I have find the answer for Second part of this question.
I was sure that there must be a way to do it and that's why I made it as my Favorite question.
//
var newMcTitle:Array = [];
//put all the info into array
var days:Array = e.target.data.split(/\n/);
for (var i=0; i<days.length; i++)
{
str = days[i];
//put the texts line by line into a textfield and put the textfield into a movie clip
var newMc:MovieClip = new MovieClip();
var newText:TextField = new TextField();
newText.text = days[i];
newMc.addChild(newText);
newMc.x = 30;
newMc.y = positionY;
newMc.scaleX = 2;
newMc.scaleY = 2;
addChild(newMc);
positionY += 30;
//unique instance names:
newMc.name = days[i];// or more generally when no arrays used
newMc.name = 'mc_' + i;
//trace(newMc.name);
//asssign unique property to be used to identify newMc
newMc.ivar = i;
//populate an array instantiated outside for-loop (eg, var newMcA:Array=[];)
newMcTitle.push(newMc);
}
And now you can use:
//if the object clicked then something must be happend to the first line in the dynamic text box
obj01.addEventListener(MouseEvent.CLICK, firstLine);
function firstLine(e:MouseEvent):void
{
flag01 += 1;
switch (flag01)
{
case 1 :
//the first line in the text box should get a different background and become more bigger
newMcTitle[0].scaleX *= 1.2;
newMcTitle[0].scaleY *= 1.2;
break;
default :
trace("None");
}
}

Update text field into movie clip from main timeline code

I'm working in a project for basketball. I have an issue, all my code works great if all my components are in the main timeline.
But as soon as I convert the text fields into a movie clip so I can animate and apply alpha value, all stops working.
what am I doing wrong ? The only solution that I could think of is writing the result of my countdown into the text field in the movie clip, but it didn't work as well.
this is my code.
function onTimer ( ev:TimerEvent ) : void {
timeRemaining--;
if (timeRemaining < 0) {
timeRemaining = 0;
loseGame();
}
else
showTime.text = formatTimeRemaining ();
var miReloj:MovieClip;
var titulo_txt:TextField = new TextField();
titulo_txt.text = formatTimeRemaining ();
addChild(miReloj);
miReloj.addChild(titulo_txt);
// miReloj.addChild(showTime1.text);
//miReloj.showTime1.text = formatTimeRemaining ();
}
There's never a value being assigned to miReloj, that's why it's null
var miReloj:MovieClip; // no assignment here
var titulo_txt:TextField = new TextField();
titulo_txt.text = formatTimeRemaining ();
addChild(miReloj); // miReloj is still null here
miReloj.addChild(titulo_txt); // cannot call method on null
But as soon as I convert the text fields into a movie clip
That's impossible. From your code it looks like what you actually want to do is to add the TextField object to a container. There's no need to use a MovieClip for that, simply create a Sprite object:
var container:Sprite = new Sprite(); // create container
var title:TextField = new TextField();
title.text = formatTimeRemaining();
addChild(container); // add container
container.addChild(title); // add title to container
Always use English for all your programming. Don't mix other languages into it. It becomes a pain to read your code and decreases the number of people that can help you if you have problems with your code.

Error #2007: Parameter child must be non-null. When Child is added within for loop

I am having this error, not sure why it appears, i believe its something with scope problem. Because i have added Child already. I can't even remove Child, the child is added within the loop, and i am not sure how to manipulate the childs that were added within the loop from the outside(after the loop has ended).
I am trying to add the child from within the loop to a viewport, but i am demonstrating the problem with removeChild to reduce the complication. Because i am trying to locate the reason of why it is giving me this error, and trying to learn what i should do.
Thanks for your time!
for (var j:int = 5; j < somedata.length; j++)
{
if(somedata[j]){
var myLoader:Loader = new Loader();
var image:Bitmap;
var url:URLRequest = new URLRequest("http://www.rentaid.info/rent/"+somedata[j]);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
myLoader.load(url);
function onImageLoaded(e:Event):void {
image = new Bitmap(e.target.content.bitmapData);
var mw:Number = bf.width*2;
var mh:Number = bf.height*1.2;
image.y = bf4.y+25;
/* if you set width and height image same with the stage use this */
image.width = mw;
image.height = mh;
var _contentHolder: Sprite;
addChild(_contentHolder);
_contentHolder.addChild(image);
}
}
removeChild(_contentHolder);
}
Edit:
function LoadImages() : void {
for (var j:int = 5; j < somedata.length; j++) {
var image:Bitmap;
myLoader = new Loader;
var urlRequest : URLRequest = new URLRequestfor ("http://www.rentaid.info/rent/"+somedata[j])
myLoader.load(urlRequest);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, LoadComplete);
}
}
function LoadComplete(event : Event) {
_contentHolder.addChild(image);
}
Or something like this?
var loadedArray:Array = new Array();
var counter:int=0;
function loadImage():void{
var loader:Loader = new Loader();
var image:Bitmap;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[counter]));
function onImageLoaded(e:Event):void {
image = new Bitmap(e.target.content.bitmapData);
loadedArray.push(e.target.content);
if(counter == somedata.length-1){
for(var i:uint = 5; i < somedata.length; i++){
image[i].x = 0 + i * 100;
addChild(_contentHolder);
_contentHolder.addChild(image[i]);
currentY += _contentHolder.height + 10;
}
}
else{
counter++;
loadImage();
You don't define _contentHolder. You also do not, currently, addChild(_contentHolder). This will be why the removeChild line is throwing an error.
Also, you do not need to addChild(image) and then add image as a child of _contentHolder. One or the other will do. In fact a DisplayObject can only be in ONE place on the display 'tree'. If you want image as a child of _contentHolder only _contentHolder.addChild(image) is necessary.
If you want all of your image instances added to the SAME _contentHolder, it would be best to declare and instantiate _contentHolder OUTSIDE the for loop; Each foor loop iteration will then be adding your images to the same Sprite object. When you remove _contentHolder, the child images will also disappear (although they will still be children of _contentHolder).
Ideally, you should not have more than one Loader operating asynchronously, as you do in your for loop. Instead of using a for loop, create a variable to track which index value you are up to and, when each image loads, increment that value and use it to check if all images are loaded. If not, load the next. This will require the Loader section of your code to be in it's own function, which gets called initially AND from onImageLoaded, if another image needs to be loaded.
The variable that tracks which index you are up to will, likewise, need to be set initially and incremented when each image loads.
In response to your edited question:
Your first new example of code does not attempt to load the NEXT image once the current image is loaded. Also, just as a tip: Function names are not normally written starting with capital letters; This prevents confusion with Class definitions.
Also your first new example of code does not call the 'LoadImages' function to initially load the first image.
Your second example looks like it should work to me. Have you actually tried this version?
The only thing I'd suggest is defining your Loader with the other variables and removing the Event.COMPLETE listener in the 'loaded' function. When adding the event listener you could also add a:
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
listener and trace out the progress of each image.
I'd also recommend adding trace statements throughout you code to see where it's getting stuck.

Unloading a Loader with actionscript 3

Hello and thank you very much for looking at this. I've spent too many hours struggling.
The code below loads a slideshow of four images, along with thumbnails for those images. It works fine.
I've added a button called "invis_button", that when pressed is supposed to remove the 3 loaders that make up the slideshow, using the removeChild command for each loader.
But this is the problem, there are 3 loaders involved in the slide-show. The removeChild command successfully removes one of the loaders (named "loader3"), but not the other two ("container3", and "thumbLoader3"). It returns an error stating "access of undefined property thumbLoader3" or "Container3".
Can someone tell me why this is ? Or better still, how to make that button (invis_button) unload the entire slide-show.
var images3:Array = ["ad_bona1.jpg", "ad_bona2.jpg", "ad_darkhawk1.jpg", "ad_darkhawk2.jpg"];
var thumbX3:Number = -375;
var thumbY3:Number = 220;
var loader3:Loader = new Loader();
loader3.load(new URLRequest("assets/ad_bona1.jpg"));
addChild(loader3);
loader3.alpha = 0;
loadThumbs3();
function loadThumbs3():void
{
var thumbLoader3:Loader;
var container3:Sprite = new Sprite();
addChild(container3);
container3.buttonMode = true;
for(var i3:uint = 0; i3 < images3.length; i3++)
{
thumbLoader3 = new Loader();
thumbLoader3.load(new URLRequest("assets/thumbs/" + images3[i3]));
thumbLoader3.x = thumbX3;
thumbLoader3.y = thumbY3;
thumbX3 += 85;
container3.addChild(thumbLoader3);
thumbLoader3.addEventListener(MouseEvent.CLICK, thumbClicked3);
}
}
function thumbClicked3(event:MouseEvent):void
{
var path3:String = event.currentTarget.contentLoaderInfo.url;
path3 = path3.substr(path3.lastIndexOf("/") + 1);
loader3.load(new URLRequest("assets/" + path3));
}
///PROBLEM BELOW, button removes only "loader3" and not the other two for some reason
invis_button.addEventListener(MouseEvent.CLICK, unload_loaders);
function unload_loaders(event:MouseEvent):void{
removeChild(loader3);
removeChild(thumbLoader3);
removeChild(container3);
}
Not sure if this is the entire reason behind what you're observing... but for starters, "thumbloader3" and "container3" are scoped locally to the loadThumbs3() method, which means once you finish executing the function, Flash's handles to those objects are lost (not to mention being in an entirely different scope)... try creating class-level properties for those two. Once that's done you should be able to successfully remove them from the stage later on.
I hope that you're also properly destroying your objects, and for the sake of brevity you just chose to omit that code above.
I've edited the code you had above & put the properties into the proper scope. (the multiple copies of thumbLoader3 are now collected inside of a vector (specialized array) so that they can be properly addressed when it comes time to destroy them)
I also wrote you a proper destroy method. ;)
I haven't tried it on my own machine, but give it a spin & see how it goes.
var images3:Array = ["ad_bona1.jpg", "ad_bona2.jpg", "ad_darkhawk1.jpg", "ad_darkhawk2.jpg"];
var thumbX3:Number = -375;
var thumbY3:Number = 220;
// begin new instance properties..
// created a new property, allowing you to group (and hold on to) the multiple thumbLoaders
var thumbLoader3Vector:Vector.<Loader> = new Vector.<Loader>();
var container3:Sprite;
// end new instance properties
var loader3:Loader = new Loader();
loader3.load(new URLRequest("assets/ad_bona1.jpg"));
addChild(loader3);
loader3.alpha = 0;
loadThumbs3();
function loadThumbs3():void
{
// this is where container3 used to be declared
container3 = new Sprite();
addChild(container3);
container3.buttonMode = true;
for(var i3:uint = 0; i3 < images3.length; i3++)
{
var tPtr:int = thumbLoader3Vector.length;
thumbLoader3Vector.push(new Loader());
// this is where thumbLoader3 used to be declared & instantiated
thumbLoader3Vector[tPtr].load(new URLRequest("assets/thumbs/" + images3[i3]));
thumbLoader3Vector[tPtr].x = thumbX3;
thumbLoader3Vector[tPtr].y = thumbY3;
thumbX3 += 85;
container3.addChild(thumbLoader3Vector[tPtr]);
thumbLoader3Vector[tPtr].addEventListener(MouseEvent.CLICK, thumbClicked3);
}
}
function thumbClicked3(event:MouseEvent):void
{
var path3:String = event.currentTarget.contentLoaderInfo.url;
path3 = path3.substr(path3.lastIndexOf("/") + 1);
loader3.load(new URLRequest("assets/" + path3));
}
///PROBLEM BELOW, button removes only "loader3" and not the other two for some reason
invis_button.addEventListener(MouseEvent.CLICK, unload_loaders);
function unload_loaders(event:MouseEvent):void{
// since the thumbLoader3 Loaders are children of container3 in the display list, we need to remove them first
for(var $i:uint = 0;$i<thumbLoader3Vector.length;$i++)
{
removeChild(thumbLoader3Vector[$i]);
// also make sure you remove the listener, so that the object will be picked up by garbage collection
thumbLoader3Vector[$i].removeEventListener(MouseEvent.CLICK, thumbClicked3);
}
// and then just set the entire vector to null
thumbLoader3Vector = null;
// remove the loader3 object & set it to null
removeChild(loader3);
loader3 = null;
// remove the container3 object & set it to null
removeChild(container3);
container3 = null;
}