Over a million developers have joined DZone.

Working with windows in Flex

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

Dear Reader,

I am putting the finishing touches on my reference application to demonstrate my wrapper for Google’s QR Code API. While doing so I decided to see what it would take to have the image pop up in a new window. Originally I had it displaying on the right side of the main window but aesthetically, that just didn’t do it for me.

“A journey of a thousand steps begins with a subclass…”

I created an ActionScript subclass of the spark Window class thinking that I would then subclass it as MXML and do the visual parts. This technique called “Code Behind” is considered a best practice when building Flex components. However, once I started working on it, I realized that I only needed 2 graphical elements. It just seemed easier to code it all in AS.

The Constructor

The main body of code in this window is in the constructor. We hand in the two pieces of information that it needs to set things up, the actual image to display and the type of image to save. In the reference application, the user is presented with 2 options for image type, PNG and JPG. It should be noted that I don’t actually validate that here although down below, if it is not a PNG then the user is getting a JPG, regardless of what they specified.

public function ImageWindow(thisImage:Image,thisImageType:String)
{
super();
this.showStatusBar=false;

I always turn of the status bar on windows that aren’t the main application window. Unless I know I am going to use it, I turn it off on the main application window as well. For the most part, it is just wasted screen real estate.

In this next section, we actually create the 2 graphical elements of the window, the image itself and the Save button. After we create them, we create a VGroup to position them for us. Once we have added both the image and the button to the VGroup, we add the vGroup to the Window so it and all of it’s elements will display.

/* 
* Image
*/
imageType = thisImageType;
qrCodeImage = thisImage;
qrCodeImage.x = 0;
qrCodeImage.y = 0;
this.width = qrCodeImage.width+10;
this.height = qrCodeImage.height+30;
qrCodeImage.visible = true;


/*
* Button
*/
btnSave.label = "Save";
btnSave.y = thisImage.height+10;
btnSave.x = 0;
btnSave.visible = true;
btnSave.addEventListener(MouseEvent.CLICK,imageSave);


/*
* Vertical Group
*/
var vg:VGroup = new VGroup();
vg.horizontalAlign="center";
vg.addElement(qrCodeImage);
vg.addElement(btnSave);
this.addElement(vg);
return;
} // public function ImageWindow(thisImage:Image,thisImageType:String)

Saving the image

This code was originally in the main application. It didn’t really belong to the QRCode.as but it never felt right in the main application either. When I created ImageWindow.as, I realized I had found it it’s home. imageSave() is called when the Save button is clicked.

The first thing it does is create a BitmapData and load the image into it. Next it determines the type of image to create. As I said earlier, even though PNG and JPG are valid options, the way the code reads, it is either PNG or you are getting a JPG. Once the image is encoded into a ByteArray and a default name is set, we use the FileReference class to save it. This will open the operating system’s native Save As dialog and allow you to change the name and place it in the proper folder.

The final thing we do here is close the window. If you have saved it, that is really all you can do in this window. So you might as well get rid of it.

protected function imageSave(event:Event):void
{
var bmpd:BitmapData = new BitmapData(qrCodeImage.width,qrCodeImage.height);
bmpd.draw(qrCodeImage);

var imgByteArray:ByteArray = null;
var fileName:String = "";

if (imageType=="PNG") {
var pngenc:PNGEncoder = new PNGEncoder();
imgByteArray = pngenc.encode(bmpd);
fileName = "qrCode.png";
} else {
var jpgenc:JPEGEncoder = new JPEGEncoder(100);
imgByteArray = jpgenc.encode(bmpd);
fileName = "qrCode.jpg";
} // if (grpImageType.selectedValue=="PNG")

var file:FileReference = new FileReference();
file.save(imgByteArray, fileName);
this.close();
} // protected function imageSave(event:Event):void

Using it

Ok, enough with the subclasses, lets look at how this works in an actual application.

The first thing we need is some place to store our Window. I usually do one of two things. If I know I will need more than one window, I usually create an array in the application global space. Then I can just add my windows to the array. If I know I am only going to use one, as in this case, I simply create a single variable to hold it, again in the global application space. I do not pretend that this is a best practice – the practice of storing variables in the global application space – however, for small projects such as this, it works. Regardless of how you do it, you need to make sure you have a handle to the window so that you can close it later. Otherwise, your application may not properly close and exit.

var imageWindow:ImageWindow;

When I am ready to show the graphic, it is a simple matter of instantiating the IageWindow class, passing in the image and the image type as parameters to the constructor.

Well, it would be simple if it weren’t for the fact that I am re-using the same window and to be nice, I want to make sure that if the user has moved the window off to one side, I honor their wishes and keep it there whenever I refresh it. What I end up with looks like this.

protected function displayImage(event:Event):void
{
var thisImage:Image = event.target.getImage();
var winX:int = -1;
var winY:int = -1;

Here is where we store off the current window’s X and Y coordinates. If the window doesn’t exist, this will throw and error. Since we aren’t really interested in the error, there is nothing in the catch. The final thing we do is close the existing window and null it out.

It was interesting (and by interesting I be frustrating to the point of drinking) that the window’s X and Y properties were always 0. You hae to use the X and Y coordinates of the nativeWindow property to actually find/affect the position of the window.

       try {
winX=imageWindow.nativeWindow.x;
winY=imageWindow.nativeWindow.y;
imageWindow.close();
imageWindow = null;
} catch (e:Error) {
}

Now we create the new window with the new image. For those wondering, yes, I could have simply re-used the existing window each time and rebuilt the graphic. If I were doing this for anything other than demonstration purposes, I would have. However, I wanted to show positioning windows in this post so I did it this way.

       imageWindow = new ImageWindow(thisImage,grpImageType.selectedValue.toString());
if (winX>-1) {
imageWindow.open();
imageWindow.nativeWindow.x=winX;
imageWindow.nativeWindow.y=winY;
} else {
imageWindow.open();
}
return;
} // protected function displayImage(event:Event):void

Conclusion

That’s it. The more I work on my reference application for my QR Code creator class, the smaller the actual application becomes. Moving things like the imageSave() into the control that actually deals with the image makes more sense to me. If you are curious, I did not put the imageSave method in QRCode.as for a couple of reasons. The main one was that imageSave uses the FileReference class; that is an AIR specific class. This would have limited QRCode to being an AIR only class. As it is, if you write a proxy for the Google API on your web site, you can use QRCode.as in a Flash app that serves up QR Codes on web pages. (I am not entirely sure why you would want to use but I didn’t want to limite your future creativity.)

Hopefully, next week, I will get around to cleaning up the reference app, publish it and be able to move onto another project. :)

Until next time,
I <3 |<
=C=

 

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:

Published at DZone with permission of Cal Evans, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}