Friday, January 14, 2011

AS3 DataGrid component: Part 9

In this tutorial we will learn how to insert images in a DataGrid component using AS3 with help of UILoader.

What we're doing is putting an UILoader component in the cell and giving it an URL of an image to display. Here's how it is going to look like:


First, I create the data grid in my .fla, set two columns for it (Image and Description) and create an array that holds: 1) the path to the image (which can be external and internal) and 2) description of the picture. Then I set the cellRenderer of my first column to a custom class loaderCellRenderer. Here's my code in the .fla:

import fl.data.DataProvider;
import fl.controls.dataGridClasses.DataGridColumn;

myGrid.move(10,10);
myGrid.setSize(300, 200);

var col_img:DataGridColumn = new DataGridColumn("Image");
myGrid.addColumn(col_img);
col_img.cellRenderer = loaderCellRenderer;

var col_desc:DataGridColumn = new DataGridColumn("Description");
myGrid.addColumn(col_desc);

var textFormat1:TextFormat = new TextFormat();
textFormat1.size = 16;
textFormat1.color = 0x333333;
textFormat1.bold = true;
textFormat1.font = "Arial";

myGrid.setStyle("headerTextFormat", textFormat1);

var textFormat2:TextFormat = new TextFormat();
textFormat2.size = 10;
textFormat2.font = "Verdana";

myGrid.setRendererStyle("textFormat", textFormat2);

var myData:Array = [{Image: "http://www.newgrounds.com/dump/draw/339a74f8071f1b259453624e34a00895.jpg", Description: "One"},
{Image: "http://www.newgrounds.com/dump/draw/44e45c25c50747dba0d1a5f2859eb10f.jpg", Description: "Two"}];

myGrid.dataProvider = new DataProvider(myData);
myGrid.rowHeight = 100;

Now, the loaderCellRenderer.as. This is going to be a little complicated. Alright, here we go.

We want our cell to hold an image. So it has to be an UILoader. That's why our class should extend UILoader. This class is also a custom CellRenderer, so it should follow (implement) the ICellRenderer interface.

public class loaderCellRenderer extends UILoader implements ICellRenderer

ICellRenderer is an interface, think of it as of a manual book. It contains information on what our class should contain to be a proper CellRenderer. If we implement it and our class does not match these instructions - then if we run our movie, we get warnings: "Sorry man, your class doesn't look like a CellRenderer class should look like. You should..." and gives us information on what the interface expected us to have - what we should add.

A CellRenderer must have 3 variables: _data, _listData and _selected:

protected var _data:Object;
protected var _listData:ListData;
protected var _selected:Boolean;

Then goes the constructor:

public function loaderCellRenderer()
{
super();
}

And now the methods. ICellRenderer requires us to have getters and setters for each variable, as well as a function called setMouseState (which we will leave empty for now). Here is my full code of loaderCellRenderer.as:

package 
{

import fl.containers.UILoader;
import fl.controls.listClasses.ListData;
import fl.controls.listClasses.ICellRenderer;

public class loaderCellRenderer extends UILoader implements ICellRenderer
{
protected var _data:Object;
protected var _listData:ListData;
protected var _selected:Boolean;

public function loaderCellRenderer()
{
super();
}

public function get data():Object
{
return _data;
}

public function set data(value:Object):void
{
_data = value;
source = value.Image;
}

public function get listData():ListData
{
return _listData;
}

public function set listData(value:ListData):void
{
_listData = value;
}

public function get selected():Boolean
{
return _selected;
}

public function set selected(value:Boolean):void
{
_selected = value;
}

public function setMouseState(state:String):void
{
}

}
}

Let's start from the function get data() part - if we need to get the data value, we simply return our _data value. If we need to set it - we set the _data to the specified value and (important for the UILoader to work) we set the source parameter to value.Image, because our parameter in the array in the fla that holds the path to the picture is called Image.

Getters and setters for listData and selected work simple: if we need to get a variable - we return it, if we need to set a variable - we set its value.

Thanks for reading!

Related:

AS3 DataGrid component: Part 1
AS3 DataGrid component: Part 2
AS3 DataGrid component: Part 3
AS3 DataGrid component: Part 4
AS3 DataGrid component: Part 5
AS3 DataGrid component: Part 6
AS3 DataGrid component: Part 7
AS3 DataGrid component: Part 8
AS3 DataGrid component: Part 10
AS3 DataGrid component: Part 11
AS3 DataGrid component: Part 12
AS3 DataGrid component: Part 13
AS3 DataGrid component: Part 14
AS3 DataGrid component: Part 15
AS3 DataGrid component: Part 16

16 comments:

xinlouis said...

Hi, nice tutorial.
I notice that when I scroll your sample datagrid, your pictures of the cats does not refresh, but when I tried the code on my side, my pictures refresh everytime I try to scroll my datagrid/ click on my datagrid. Why is that so?

Anonymous said...

had the same problem, try this:

if (source != value.Image) {
source = value.Image;
}

Anonymous said...

how to make 2 or more columns with images? if i apply loaderCellRenderer to 2 or more columns, pictures from these columns will be the same, i mean that this class only works for 1 column, how to extend it for more?

Kirill Poletaev said...

The source of the picture is defined in this line

source = value.Image;

It takes the whatever is in Image property of the current dataset item and displays it.

One way to do what you want is create a new renderer and just change Image to Image2 or something.

Valerian said...

ok big thx, i will try))

pete said...

Well a nice tutorial - I would also like to have 2 columns with images - but did not manage it. Could you be more specific with "create a new renderer" or maybe give an example.Thanks

pete said...

Ok I got it by adding another render as you mentioned. Many thanks for this useful Post.

Peter said...

Great tutorial.. been very useful for me.

What I am trying to change now is the url loader.

The data I want am providing looks like:

var myData:Array = [{Image: "img1",Description: "One"},{Image: "img2", Description: "Two"}];

I want img1 and img2 to be in the library.

Bit stuck there.

Kirill Poletaev said...

Create variables that are instances of the pictures, then just use addChild() on the variable.

Peter said...

Thanks.. that worked for me.
Regards

Peter said...

How I done it:

while (numChildren !=0) removeChildAt(0);
var ImageClass:Class = getDefinitionByName(_image2load) as Class;
var Image1:Bitmap = new Bitmap(new ImageClass(0,0));
addChild(Image1);


But at this point I have a new question. How do i get the cell border lines back?

Regards,
Peter

Kirill Poletaev said...

You will have to draw them yourself this time! You can create a shape object and draw the border lines using the width and height data.

Jahangir said...

Can we put any MovieClip instead of any image where MC instance will have eventlistener ??

pandacostume said...

hi, i tryed your codes and it works, but the pictures that desplayed are small, can you please tell me how to set their size?

Kirill Poletaev said...

You can set rowHeight of the DataGrid to a higher value. Hope this helps!

MindWisdom said...

Hi, thank you for this great tutorial.

How do you set cells background color ("upSkin") when the cells have IMAGES rendered into them like in the first column from this example from Part 9?

Post a Comment