I want to add dynamic checkbox in a grid componemt in AS3. Here is the link. I want to do it in Flash AS3.0 not in Flex.
For custom cells you need to you use custom cellRenderer on the column.
Main
var sampleItem1:Object = {Name:"John Alpha", Number:"555-123-0101", Email:"jalpha#fictitious.com"};
var dg:DataGrid = new DataGrid();
var dgc:DataGridColumn = new DataGridColumn("Name");
dg.addColumn(dgc);
dgc = new DataGridColumn("Number");
dgc.cellRenderer = "CustomCellRenderer"; // here you set your custom renderer for this column
dg.addColumn(dgc);
dgc = new DataGridColumn("Email");
dg.addColumn(dgc);
dg.addItem(sampleItem1);
CheckBoxCellRenderer.as
package
{
import fl.controls.CheckBox;
import fl.controls.listClasses.ICellRenderer;
import fl.controls.listClasses.ListData;
public class CustomCellRenderer extends CheckBox implements ICellRenderer {
private var _listData:ListData;
private var _data:Object;
public function CustomCellRenderer() {
}
public function set data(d:Object):void {
_data = d;
label = d.label;
}
public function get data():Object {
return _data;
}
public function set listData(ld:ListData):void {
_listData = ld;
}
public function get listData():ListData {
return _listData;
}
}
}
source1 source2
Related
I wrote a simple function "adone" to add things to the stage and today I decided to make it add child to other objects as well but the test function "ad2" I made is not working right. what do you suggest?
package {
import flash.display.MovieClip;
public class main extends MovieClip {
public var ui:Array = new Array;
public var splz:Array = new Array;
public var pows:powsys = adone("powsz",powsys,ui,400,240);
public var s1:powsyspsl = ad2("s1",powsyspsl,splz,100,100,"powsz");
public function main() {
}
public function adone(nm,tp,lst,ex=0,ey=0) {
nm = new tp();
addChild(nm);
lst.push(nm);
nm.x = ex;
nm.y = ey;
}
public function ad2(nm,tp,lst,ex=0,ey=0,par=null) {
nm = new tp();
par.addChild(nm);
lst.push(nm);
nm.x = ex;
nm.y = ey;
}
}
}
public var pows:powsys = adone("powsz",powsys,ui,400,240);
you are setting first parameter "powsz" but you're not using this parameter, you're just changing it with nm = new tp(); when your adone() function worked, so it is looking like working properly...
and here...
public var s1:powsyspsl = ad2("s1",powsyspsl,splz,100,100,"powsz");
you're not making the same fault as in "adone()" so it is still a string variable and you're trying to add a child to a string variable "powsz" here? i think you should fix that
par.addChild(nm);
but if you don't wanna fix things but you wanna your code work unproperly you can try this
public function ad2(nm,tp,lst,ex=0,ey=0,par=null) {
nm = new tp();
par = new tp();
par.addChild(nm);
lst.push(nm);
nm.x = ex;
nm.y = ey;
}
And all this stuff looks like a joke! Your problems not going to be solved by this way, you have to fix your whole code and logic.. You're using lots of unnecessary stuff and wrong ways to make what you want...
changed the code to:
package {
import flash.display.MovieClip;
public class main extends MovieClip {
public var ui:Array = new Array ;
public var splz:Array = new Array ;
public var pows:powsys = adone("pows",powsys,ui,400,240);
public var s1:powsyspsl = adone("s1",powsyspsl,splz,100,100,pows);
public function main() {
}
public function adone(nm,tp,lst,ex=0,ey=0,par=null) {
nm = new tp ;
if (par) {
par.addChild(nm);
} else {
addChild(nm);
}
lst.push(nm);
nm.x = ex;
nm.y = ey;
}
}
}
the "par" var returns null both times in the trace. and that means 2nd object is added to the stage not to 1st one.
Untested....
package {
import flash.display.MovieClip;
public class main extends MovieClip {
public var ui:Array = new Array;
public var splz:Array = new Array;
public var pows:powsys = adone(powsys,ui,400,240);
public var s1:powsyspsl = adone(powsyspsl,ui,400,240,pows);
public function main() {
}
public function adone(tp,lst,ex=0,ey=0,par=null):Object {
var nm = new tp();
if (par) {
par.addChild(nm);
} else {
addChild(nm);
}
lst.push(nm);
nm.x = ex;
nm.y = ey;
return nm;
}
}
}
This game is a board game so it need to pass information but mostly not dynamically.
Is this the correct definition of a Custom Event?
package
{
import flash.events.Event;
public class Set extends Event
{
public var addsub:Boolean;
public var kanaex:String;
public var valueex:uint;
public var xx:uint;
public var yy:uint;
public static const BOARD_SET_CHANGED:String = "BoardSetChanged";
public static const BOX_SET_CHANGED:String = "BoxSetChanged";
public function Set(type:String, addsub1:Boolean, kanaex1:String, valueex1:uint, xx1:uint,yy1:uint, bubbles:Boolean = false, cancelable:Boolean = false)
{
super(type, bubbles, cancelable);
addsub = addsub1;
kanaex = kanaex1;
valueex= valueex1;
xx = xx1;
yy = yy1;
}
override public function clone():Event
{
return new Set(type, addsub, kanaex,valueex,xx,yy, bubbles, cancelable );
}
override public function toString():String
{
return formatToString("BoardSetChanged","addsub","kanaex","valueex","xx","yy","bubbles", "cancelable");
}
}
}
If so why does this code leave the
event attributes undefined?
import Set;
import flash.events.*;
this.addEventListener(Set.BOARD_SET_CHANGED, Exclusion);
private function Exclusion(e:Event)
{
var a:Boolean = e.addsub;
var b:uint = e.xx;
var c:uint = e.yy;
if (a == true)
{exclusionx.push(b);
exclusiony.push(c);
}
else if (a == false)
{exclusionx.pop();
exclusiony.pop();
}
}
Try to change the parameter of Exclusion to Set
private function Exclusion(e:Set):void {
}
Having trouble adding a SharedObject to a .AS file, I am trying to add the users name to the .flv file in red 5 like "username_myfile" I am not sure I am adding the code thats saves the name in the correct part of the class. is there a proper way to add a SharedObject to a .AS file?
--
added:
import flash.net.SharedObject;
package app
{
import flash.display.BitmapData;
import flash.display.Stage;
import flash.external.ExternalInterface;
**import flash.net.SharedObject;**
public class DataHolder
{
private static var dataHolder:DataHolder;
public var savedstuff:SharedObject = SharedObject.getLocal("myStuff2","/");
if (savedstuff.size > 0)
{
public var username = savedstuff.data.username;
}
public var filename:String = (String(username) + "_myfile");
public var rtmpPath:String = "rtmp://numbershere.compute-1.amazonaws.com/oflaDemo/";
public var recorder:Recorder;
public var navigation:Navigation;
public var cameraFPS:Number = 30;
public var cameraWidth:Number = 640;
public var cameraHeight:Number = 480;
public var cameraQuality:Number = 88;// camera quality
public var timelimit:Number = 25;// limit count of seconds
public var stage:Stage;
public function DataHolder()
{
if (dataHolder)
{
throw new Error("Only one DataHolder instance should be instantiated");
}
}
public static function getInstance():DataHolder
{
if (dataHolder == null)
{
dataHolder = new DataHolder();
}
return dataHolder;
}
}
}
Remove the conditional declaration of your shared object and declare as usual, ie:
private var savedStuff:SharedObject;
Then, in your constructor:
try {
savedStuff = SharedObject.getLocal("savedData");
} catch (error) {
cookiesActive = false;
};
Then check cookiesActive==true to save data to the SharedObject, eg:
if (cookiesActive) {
savedStuff.data.levelsFinished = 1;
}
In my AIR application, I try to dispatch a custom event from a class to main window.
This class is use to call httpservice. My goal is to send a custom window when the httpservice result is send.
package fr.inter.DataProvider
{
import flash.events.Event;
import flash.events.EventDispatcher;
import fr.inter.config.urlManager;
import fr.kapit.introspection.components.DisplayListComponent;
import mx.collections.XMLListCollection;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
[Event(name="evtPatSelect", type="flash.events.Event")]
public class sPatient
{
private var _phppaIndex:String;
private var _phppaNomU:String;
private var _phppaPrenom:String;
private var phpSearchPatNom:HTTPService;
public function sPatient()
{
}
public function sPhpSearchPat(p:Object):void
{
phpSearchPatNom = new HTTPService();
phpSearchPatNom.method="POST";
phpSearchPatNom.resultFormat = "e4x";
phpSearchPatNom.addEventListener(ResultEvent.RESULT,resultListePatient);
phpSearchPatNom.addEventListener(FaultEvent.FAULT,serviceFault);
var urlPhp:urlManager=new urlManager();
phpSearchPatNom.url = urlPhp.urlService() + "20SearchNom.php";
phpSearchPatNom.send(p);
}
private function resultListePatient( event:ResultEvent ):void
{
var xmlList:XMLList = XML(event.result).patientPHP;
var xmlListColl = new XMLListCollection(xmlList);
if(xmlListColl.length==1)
{
_phppaIndex = xmlListColl.getItemAt(0).paIndex;
_phppaNomU = xmlListColl.getItemAt(0).paNomU;
_phppaPrenom = xmlListColl.getItemAt(0).paPrenom;
var evtPat:Event = new Event("evtPatSelect");
var evdips:EventDispatcher = new EventDispatcher();
evdips.dispatchEvent(evtPat);
}
}
private function serviceFault( event:FaultEvent )
{
trace( event.fault.message );
}
public function get phppaIndex():String
{
return _phppaIndex;
}
public function set phppaIndex(value:String):void
{
_phppaIndex = value;
}
public function get phppaNomU():String
{
return _phppaNomU;
}
public function set phppaNomU(value:String):void
{
_phppaNomU = value;
}
public function get phppaPrenom():String
{
return _phppaPrenom;
}
public function set phppaPrenom(value:String):void
{
_phppaPrenom = value;
}
}
}
In main window I've added a eventlistener but this seems not works.
Can you help me to solve that?
Thanks
First, extend the sPatient class as an EventDispatcher
public class sPatient extends EventDispatcher {
Then, create a class for your custom Event
public class MyCustomEvent extends Event {
public static const CUSTOM_TITLE:String = "custom_title";
public var eventData:Object;
public function CustomEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, data:Object = null) {
super(type, bubbles, cancelable);
if(data != null) eventData = data;
}
public override function clone():Event {
return new CustomEvent(type, bubbles, cancelable);
}
public override function toString():String {
return formatToString("CustomEvent", "type", "bubbles", "cancelable", "eventPhase");
}
}
Then in your sPatient class, go:
this.dispatchEvent(new MyCustomEvent(MyCustomEvent.CUSTOM_TITLE));
And listen for it like so
sPatientInstance.addEventListener(MyCustomEvent.CUSTOM_TITLE,functionHandler);
the code below sets up a List object in the main controller class that uses a custom cell renderer (CustomListCell class). the CustomListCell class creates a Button object for the cell that will be used to delete itself from the List's DataProvider.
how can i properly access the parent List object from its custom cell renderer?
//Controller Class
private function createList():void
{
provider = new DataProvider(data);
list = new List();
list.width = 200;
list.height = 400;
list.rowHeight = 50;
list.dataProvider = provider;
list.setStyle("cellRenderer", CustomListCell);
}
-----
//CustomListCell Class
import fl.controls.Button;
public class CustomListCell extends Sprite implements ICellRenderer
{
public function CustomListCell()
{
var button:Button = new Button();
button.label = "Delete Cell";
button.addEventListener(MouseEvent_MOUSE_DOWN, deleteCellHandler);
addChild(button);
}
private function deleteCellHandler(evt:MouseEvent):void
{
//Access List/DataProvider Here
}
//required implemented ICellRenderer functions follow
}
UPDATE
the following is my working custom renderer that implements ICellRenderer with Flash v3 List component. the List's dataProvider consists of 2 elements for each cell: randomColor and randomNumber.
package
{
//Imports
import fl.controls.Button;
import fl.controls.List;
import fl.controls.listClasses.ICellRenderer;
import fl.controls.listClasses.ListData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.geom.ColorTransform;
//Class
public class TouchListRenderer extends Sprite implements ICellRenderer
{
//Properties
private var cellWidthProperty:Number;
private var cellHeightProperty:Number;
private var dataProperty:Object;
private var listDataProperty:ListData;
private var selectedProperty:Boolean;
//Cell Display Objects
private var backgroundCanvas:MySprite = new MySprite();
private var numberTextField:TextField = new TextField();
private var button:Button = new Button();
//Constructor
public function TouchListRenderer()
{
}
//Size Setter (Getter Functions Intentionally Omitted)
public function setSize(width:Number, height:Number):void
{
cellWidthProperty = width;
cellHeightProperty = height;
}
//Data Setter
public function set data(value:Object):void
{
dataProperty = value;
}
//Data Getter
public function get data():Object
{
return dataProperty;
}
//List Data Setter
public function set listData(value:ListData):void
{
listDataProperty = value;
}
//List Data Getter
public function get listData():ListData
{
return listDataProperty;
}
//Selected Setter
public function set selected(value:Boolean):void
{
selectedProperty = value;
layout();
}
//Selected Getter
public function get selected():Boolean
{
return selectedProperty;
}
//Size And Layout
private function layout():void
{
var newColor:ColorTransform = new ColorTransform();
newColor.color = dataProperty.randomColor;
backgroundCanvas.transform.colorTransform = newColor;
backgroundCanvas.scaleX = cellWidthProperty / backgroundCanvas.width;
backgroundCanvas.scaleY = cellHeightProperty / backgroundCanvas.height;
numberTextField.text = dataProperty.randomNumber;
numberTextField.autoSize = TextFieldAutoSize.LEFT;
numberTextField.textColor = 0xFFFFFF;
numberTextField.x = 50;
numberTextField.y = cellHeightProperty / 2 - numberTextField.height / 2;
numberTextField.border = true;
numberTextField.selectable = false;
button.label = "Delete";
button.x = cellWidthProperty - button.width - 50;
button.y = cellHeightProperty / 2 - button.height / 2;
button.drawNow();
button.addEventListener(MouseEvent.MOUSE_DOWN, buttonClickEventHandler);
addChild(backgroundCanvas);
addChild(numberTextField);
addChild(button);
}
//Button Click Event Handler
private function buttonClickEventHandler(evt:MouseEvent):void
{
List(listDataProperty.owner).removeItemAt(listDataProperty.index);
}
//Style Setter
public function setStyle(style:String, value:Object):void
{
}
//Mouse State Setter
public function setMouseState(state:String):void
{
}
}
}
package
{
import flash.display.Sprite;
public class MySprite extends Sprite
{
public function MySprite()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0, 0, 10, 10);
graphics.endFill();
}
}
}
ugh! the answer was in front of me the whole time! next time remind me to check the docs:
List(listData.owner)
fl.controls.listClasses.ListData.owner
There are multiple ways to do this.
Here is a very hacky solution: Use an icon, and have that icon dispatch a close event.
The idea is you'll place a custom MovieClip in each list cell as icon. That icon will dispatch an event with the index of the cell clicked so you can remove it.
1st step: Make a basic custom event to pass cell index through:
package{
import flash.events.Event;
public class CloseEvent extends Event{
public static const CLOSE:String = 'close';
public var index:int;
public function CloseEvent(type:String,bubbles:Boolean = true,cancelable:Boolean=true){
super(type,bubbles,cancelable);
}
}
}
2nd step:: Draw a close icon or something, convert it to MovieClip and Export for Actionscript
3rd step: Add the event listener to dispatch the custom event when the close icon is clicked.
Inside the close icon Movie Clip I've placed the following actions:
import fl.controls.listClasses.CellRenderer;
//setup click
buttonMode = true;
if(parent) parent.mouseChildren = true;
addEventListener(MouseEvent.MOUSE_DOWN,dispatchClose);
//setup event
var closeEvent:CloseEvent = new CloseEvent(CloseEvent.CLOSE,true);
if(parent) closeEvent.index = CellRenderer(parent).listData.index;
//listen to click and pass on
function dispatchClose(event:MouseEvent):void {
dispatchEvent(closeEvent);
}
Very basic stuff, listen for mouse down, create an event and set the index and dispatch that event on click. The icon is added to a cell renderer, therefor the cell render is it's parent which it has a listData property among others, which holds the index of the cell.
So here's how the test snippet looks:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1),icon:Close});
ls.dataProvider = dp;
addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
ls.removeItemAt(event.index);
}
Since the CloseEvent bubbles, we can catch it from outside the cell renderer's icon and tell the list to remove the item at that index. It's possible to do that within the icon, but it will be necessary to 'climb' up the hierarchy all the way to the list, and it's pretty hacky already.
I did this because, I was probably as lazy as #TheDarkIn1978 :P to implement the ICellRenderer functions. Then I looked at question code again and didn't understand why the custom cell extends a Sprite, when CellRenderer already implements the ICellRenderer functions already.
So here is my attempt to do it in a less hacky manner:
package{
import fl.controls.*;
import fl.controls.listClasses.*;
import fl.data.*;
import flash.events.*;
public class SCListCell extends CellRenderer implements ICellRenderer{
protected var closeButton:Button;
protected var closeEvent:CloseEvent;
override protected function configUI():void {
super.configUI();
closeButton = new Button();
closeButton.label = 'x';
closeButton.buttonMode = true;
closeButton.setSize(30,20);
closeButton.drawNow();
closeButton.addEventListener(MouseEvent.CLICK,close);
addChild(closeButton);
closeEvent = new CloseEvent(CloseEvent.CLOSE);
}
private function close(event:MouseEvent):void{
closeEvent.index = listData.index;
dispatchEvent(closeEvent);
}
override protected function drawLayout():void{
mouseChildren = true;
closeButton.x = width-closeButton.width;
}
}
}
Used the same CloseEvent to pass the index, and the custom cell has direct access to the listData object to fetch the index, so the sample snippet looks like this:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;
addEventListener(CloseEvent.CLOSE,deleteItem);
function deleteItem(event:CloseEvent):void {
ls.removeItemAt(event.index);
}
ls.setStyle('cellRenderer',SCListCell);
So to answer your question:
how can i properly access the parent
List object from its custom cell
renderer?
You can use the listData property of the cell renderer.
You can if you want to, but it means going up a few levels:
package{
import fl.controls.*;
import fl.controls.listClasses.*;
import fl.data.*;
import flash.events.*;
public class SCListCell extends CellRenderer implements ICellRenderer{
protected var closeButton:Button;
override protected function configUI():void {
super.configUI();
closeButton = new Button();
closeButton.label = 'x';
closeButton.buttonMode = true;
closeButton.setSize(30,20);
closeButton.drawNow();
closeButton.addEventListener(MouseEvent.CLICK,close);
addChild(closeButton);
}
private function close(event:MouseEvent):void{
List(this.parent.parent.parent).removeItemAt(listData.index);
}
override protected function drawLayout():void{
mouseChildren = true;
closeButton.x = width-closeButton.width;
}
}
}
Which leaves the list creation part as simple as:
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
for(var i:int = 0 ; i < 30 ; i++) dp.addItem({label:'item'+(i+1)});
ls.dataProvider = dp;
ls.setStyle('cellRenderer',SCListCell);
CloseEvent isn't needed in this case.
HTH