Flex AdvancedDataGrid - ColumnOrder With Formatter and ItemRenderer Question For Experts - apache-flex

I have a advanceddatagrid that has around 15 columns. Some are string,
some are numbers. I have shown 4 columns below.
The number columns have formatting done for zero precision and 2
digits precision. The itemRenderer is just to show Blue Color if the
number is +ve and Red Color if the number is -ve.
It looks something like below
<mx:columns>
<mx:AdvancedDataGridColumn dataField="Name" textAlign"left"/>
<mx:AdvancedDataGridColumn dataField="Time" textAlign="right"/>
<mx:AdvancedDataGridColumn dataField="Score" textAlign="right" formatter="{zeroPrecisionFormatter}" sortable="true" itemRenderer="ColorRenderer" />
<mx:AdvancedDataGridColumn dataField="Average" textAlign="right" headerWordWrap="true" formatter="{twoPrecisionFormatter}" itemRenderer="ColorRenderer" />
...
I am trying to save the users setting of column order when he closes
the application and reload with the same order when the user opens the
applications. I am using SharedObjects and below is the code.
for(var i:int=0; i< adgrid.columns.length;i++){
var columnObject:Object = new Object();
columnObject.columnDataField = adgrid.columns[i].dataField as String;
columnObject.columnHeader =adgrid.columns[i].headerText as String;
columnObject.width = adgrid.columns[i].width;
columnArray.push(columnObject);
}
and then I save the columnArray to SharedObject.
I retrive them using the below code
for(var i:int=0;i<columnArray.length;i++){
adgrid.columns[i].dataField =columnArray[i].columnDataField;
adgrid.columns[i].headerText =columnArray[i].columnHeader;
adgrid.columns[i].width = columnArray[i].width;
}
How can I save and reload the Formatter and ItemRenderer data .
I am having trouble saving the formatter and itemrenderer and
reloading it again.
I would really appreciate if you can shown the code.
How can I reshuffle the columns but can preserve all the properties of it to though sharedobject and recover it again.

private function loadLayout(name:String="custom"):void {
var storedLayoutData:SharedObject;
storedLayoutData = SharedObject.getLocal("layouts");
if (storedLayoutData.data["pocketBankDG_"+name]) {
var columns:Array = new Array();
var index:int = 0;
for each (var column:Object in storedLayoutData.data["pocketBankDG_"+name]["columns"]) {
for ( var key:String in column) {
var propClass:Class = getDefinitionByName(column[key].propClassName) as Class;
adgOperations.columns[index][key] = column[key].propValue as propClass;
}
index++
}
} else {
saveLayout("default");
openSettingsWindow();
}
}
private function saveLayout(name:String="custom"):void {
var storedLayoutData:SharedObject;
storedLayoutData = SharedObject.getLocal("layouts");
if (!storedLayoutData.data["pocketBankDG"]) storedLayoutData.data["pocketBankDG_"+name] = new Object();
var columns:Array = new Array();
for each(var column:AdvancedDataGridColumn in adgOperations.columns) {
var describeType:XML = flash.utils.describeType(column);
var accessoriesList:XMLList = describeType..accessor;
var data:Object = new Object;
for each(var accessor:XML in accessoriesList) {
if (accessor.#access=="readwrite") {
var propClassName:String = getQualifiedClassName(column[accessor.#name]);
var propValue:* = column[accessor.#name];
if (propClassName=="String" || propClassName=="int" || propClassName=="Boolean" ||
propClassName=="Number" || propClassName=="uint") {
data[accessor.#name] = {}
data[accessor.#name].propClassName = propClassName;
data[accessor.#name].propValue = propValue;
}
}
}
columns.push(data);
}
storedLayoutData.data["pocketBankDG_"+name]["columns"] = columns;
storedLayoutData.flush();
}

Related

Flex Android application suspends when using jpeg image

I have a flex application in which I have to convert a jpeg picture taken by camera using base64 converter and then upload the result to sqlite database (as MEDIUMBLOB). The code looks like this:
MXML declarations of images:
<s:Group width="480" height="304">
<s:Label x="0" y="0" width="100%" height="34" backgroundColor="#4D4D4D"
color="#FFFFFF" fontSize="30" text=" Select photo" verticalAlign="middle"/>
<s:Image id="image" x="10" y="42" width="217" height="246" />
<s:Image id="image2" x="10" y="42" width="217" height="246" source = "#Embed(source='skins/PhotoNotAvailable.jpg')"/>
<s:Button x="235" y="42" width="235" height="84" label="Take a Picture"
click="captureImage(event)" enabled="{CameraUI.isSupported}" fontSize="30"/>
<s:Button x="235" y="150" width="235" height="70" label="Delete"
click="deletePhoto(event)" fontSize="30"/>
</s:Group>
Scripts for taking a picture and convertion:
//Taking the pictures
protected function application1_applicationCompleteHandler(event:FlexEvent):void {
image.setVisible(true);
image2.setVisible(false);
if (CameraUI.isSupported){
var mediaPromise:MediaPromise;
camera = new CameraUI();
camera.addEventListener(MediaEvent.COMPLETE, onComplete);
camera.addEventListener(ErrorEvent.ERROR, onError);
} else {
}
}
protected function view1_activateHandler(event:Event):void
{
conn = data as SQLConnection;
}
private function captureImage(event:MouseEvent):void {
camera.launch(MediaType.IMAGE);
}
private function onError(event:ErrorEvent):void {
trace("error has occurred");
}
private function onComplete(event:MediaEvent):void {
var mediaPromise:MediaPromise = event.data;
image.source = mediaPromise.file.url;
pictureTaken = true;
}
//Convertion and uploading to database
protected function AddHandler(event:MouseEvent):void
//irrelevant code skipped
insertStmt = new SQLStatement();
insertStmt.sqlConnection = conn;
var insertSQL:String = ("INSERT INTO RecipeDB (RecipeID, Name, Category, Origin, Recipe, Favorite, Image)" + "VALUES (:RecipeID, :Name, :Category, :Origin, :Recipe, :Favorite, :Image)");
insertStmt.text = insertSQL;
if(pictureTaken)
{
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray = jencoder.encode(image.bitmapData);
var baseEncoder:Base64Encoder = new Base64Encoder();
baseEncoder.encodeBytes(imageByteArray);
encodedBytes = baseEncoder.toString();
}
else
{
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray = jencoder.encode(image2.bitmapData);
var baseEncoder:Base64Encoder = new Base64Encoder();
baseEncoder.encodeBytes(imageByteArray);
encodedBytes = baseEncoder.toString();
}
insertStmt.parameters[":RecipeID"] = ID as int;
insertStmt.parameters[":Name"] = NameArea.text;
insertStmt.parameters[":Category"] = TypeArea.text;
insertStmt.parameters[":Origin"] = OriginArea.text;
insertStmt.parameters[":Recipe"] = RecipeArea.text;
insertStmt.parameters[":Favorite"] = 0 as int;
insertStmt.parameters[":Image"] = encodedBytes;
insertStmt.execute();
}
//Deleting photo
protected function deletePhoto(event:MouseEvent):void
{
pictureTaken = false;
image.setVisible(false);
image2.setVisible(true);
}
Now, if no picture was taken, the program uploads skins/PhotoNotAvailable.jpg to the DB correctly, but if the picture was taken or taken and deleted, the program hangs (android asks if to close it or wait). I have checked the size of taken pictures and it does not exceed MEDIUMBLOB`s size (picture has ca. 2 MBytes). What could be wrong?
My first thought from your description of what happens is "a breakpoint." The only time my phone gives me that message is when I'm debugging and it's stopped on a break point for too long.
You might cast your event.data as MediaPromise
private function onComplete(event:MediaEvent):void {
var mediaPromise:MediaPromise = event.data as MediaPromise;
image.source = mediaPromise.file.url;
pictureTaken = true;
}
Though that may just be a copying error.
So far as I can tell you don't need to base64 encode the image data. It's already encoded and ready to be inserted into a database. Perhaps "double-encoding" is somehow creating a problem. ???
I would change
if(pictureTaken)
{
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray = jencoder.encode(image.bitmapData);
var baseEncoder:Base64Encoder = new Base64Encoder();
baseEncoder.encodeBytes(imageByteArray);
encodedBytes = baseEncoder.toString();
}
else
{
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray = jencoder.encode(image2.bitmapData);
var baseEncoder:Base64Encoder = new Base64Encoder();
baseEncoder.encodeBytes(imageByteArray);
encodedBytes = baseEncoder.toString();
}
insertStmt.parameters[":RecipeID"] = ID as int;
insertStmt.parameters[":Name"] = NameArea.text;
insertStmt.parameters[":Category"] = TypeArea.text;
insertStmt.parameters[":Origin"] = OriginArea.text;
insertStmt.parameters[":Recipe"] = RecipeArea.text;
insertStmt.parameters[":Favorite"] = 0 as int;
insertStmt.parameters[":Image"] = encodedBytes;
insertStmt.execute();
to
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray;
if(pictureTaken)
{
imageByteArray = jencoder.encode(image.bitmapData);
}
else
{
imageByteArray = jencoder.encode(image2.bitmapData);
}
insertStmt.parameters[":RecipeID"] = ID as int;
insertStmt.parameters[":Name"] = NameArea.text;
insertStmt.parameters[":Category"] = TypeArea.text;
insertStmt.parameters[":Origin"] = OriginArea.text;
insertStmt.parameters[":Recipe"] = RecipeArea.text;
insertStmt.parameters[":Favorite"] = 0 as int;
insertStmt.parameters[":Image"] = imageByteArray;
insertStmt.execute();
If for some reason you still want the base64 encoding and it's not creating the problem, I would still suggest refactoring the code like this to save duplication since the only thing that varies between the two if branches is the source of the bitmap data.
var jencoder:JPEGEncoder = new JPEGEncoder(75);
var imageByteArray:ByteArray;
if(pictureTaken)
{
imageByteArray = jencoder.encode(image.bitmapData);
}
else
{
imageByteArray = jencoder.encode(image2.bitmapData);
}
var baseEncoder:Base64Encoder = new Base64Encoder();
baseEncoder.encodeBytes(imageByteArray);
encodedBytes = baseEncoder.toString();
However, this is just a first stab at it. It would be useful to see the code all together. I'm assuming that encodedBytes is a String available to the whole class? I can't see how/when AddHandler is invoked, so I also can't tell variable states when it is called (which could be related to the problem). It would also be useful to know what's happening after the AddHandler is completed. Perhaps it's an error occurring after the insert statement that is hanging up?
Did you debug it and get any errors to share?
I know the post is a month old, so maybe you already figured it out. Maybe you could share it so others don't make the same mistake. Either way, I hope this can help someone.

how to assign dataProvider to DataGrid Dyanmically in flex?

i done as follows
i have a method with brings data of particular table, as given my parameter to that method,
now i want to fetch data from corresponding table and it too list, and send back flex and form dynamically Grid & add dataprovider dynamically as for its corresponded table colomns in flex side ?
Remote objec(java class)
public List<List<String>> getMasterTableData(String name)
{
String designMaster = "tbl_design_master"+name;
String masterTableName = "tbl_master"+name;
String[][] res ;
List<List<String>> list = new ArrayList<List<String>>();
try
{
st = connection.createStatement();
ResultSet rs1 = st.executeQuery("select * from "+designMaster);
int len = 0;
while(rs1.next())
{ len++; }
ResultSet rs2 = st.executeQuery("select * from "+masterTableName);
while(rs2.next())
{
List<String> ll = new ArrayList<String>();
for(int i=1;i<=len; i++)
{
ll.add(rs2.getString(i));
}
list.add(ll);
}
}
catch (SQLException e) {
e.printStackTrace();
}
return list;
}
flex code :
<mx:RemoteObject id="RO" destination="adminServiceImpl">
<mx:method name="getMasterDesign" result="getMasterDesignRH(event)" fault="FH(event)" />
<mx:method name="getMasterTableData" result="getMasterTableDataRH(event)" fault="FH(event)"/>
</mx:RemoteObject>
<mx:Script>
<![CDATA[
[Bindable] private var ac:ArrayCollection = new ArrayCollection();
public function init(Str:String):void
{
RO.getMasterDesign(Str);
Application.application.selectedgridItem = Str;
RO.getMasterTableData(Str);
}
private function getMasterDesignRH(event:ResultEvent):void
{
Application.application.designList = event .result as ArrayCollection;
var aColumns:Array = new Array();
for(var i:int=0; i< Application.application.designList.length; i++)
{
var dgc:DataGridColumn = new DataGridColumn();
dgc.headerText = Application.application.designList.getItemAt(i).colName;
//dgc.dataField = Application.application.designList.getItemAt(i).colName;
aColumns.push(dgc);
}
mainGrid.columns = aColumns;
}
private function getMasterTableDataRH(event:ResultEvent):void
{
ac = event.result as ArrayCollection;
mainGrid.dataProvider = ac;
}
private function FH(event:FaultEvent):void{
Alert.show(event.fault.faultString);
}
]]>
</mx:Script>
<mx:HBox width="100%" height="80%">
<mx:DataGrid id="mainGrid" width="100%" height="100%" />
</mx:HBox>
getMasterDesign is an ArrayCollection, which is filled with the column names and components to be displayed
Ex : getMasterDesign(emp)
empMasterDesign table looks like as follows
colName component
--------------------
EmpName textBox
empSal textBox
empDesi ComboBox
empMasterData:
empName | EmpSal | EmpDesi
abc 1000 Cler## Heading ##ck
xyz 2000 Manager
Now i want this create a Datagrid in flex dynamically by using its design & master data table in action script i done everyting , my dataGrid had formed as for his master design,but data is not showing ?
You must set the dataField to the appropriate value. From the given data, it looks like colName field in the metadata and its corresponding name in the table are not the same. For example it is EmpName in the design and empName in the original table; none of the fields match - empSal vs EmpSal, empDesi vs EmpDesi. Fix that, assign colName to the dataField, and you should be good to go.

How to read the Dynamic form Child data in Flex?

i created a form dynamically by adding each component in action script,
now i want to get back the text/data entered in to that each component dynamically?
private function loadAllComponents():void
{
var formItemArray:Array = new Array();
for(var i:int=0; i< Application.application.designList.length; i++)//which had the colonName, colComponet to be dispalyed,
{
var fm:FormItem = new FormItem();
fm.label = Application.application.designList.getItemAt(i).colName;
var comp:String = Application.application.designList.getItemAt(i).component;
switch(comp)
{
case "TextBox":
var ti:TextInput = new TextInput();
ti.id = Application.application.designList.getItemAt(i).component;
fm.addChild(ti);
break;
case "TextArea":
var ta:TextArea = new TextArea();
ta.id = Application.application.designList.getItemAt(i).colName;
fm.addChild(ta);
break;
case "ComboBox":
var mycb:myComboBox = new myComboBox();
mycb.getAllMasterCBData(Application.application.selectedgridItem, Application.application.designList.getItemAt(i).colName);
fm.addChild(mycb);
break;
case "DateField":
var df:DateField = new DateField();
df.id = Application.application.designList.getItemAt(i).component;
fm.addChild(df);
break;
}
myform.addChild(fm);
}
}
private function saveToDb():void // Here i wan to read all the formdata
{
var formItems:Array = myform.getChildren();
for each (var item:UIComponent in formItems)
{
if (item is TextInput)
{
var text:String = Object(item).text;
Alert.show("came here");
}
else if (item is DateField)
{
var date:Date = DateField(item).selectedDate;
}
}
}
]]>
</mx:Script>
<mx:Form id="myform" cornerRadius="5" borderColor="#B7BABC" borderStyle="solid" width="100%" height="100%" />
<mx:HBox width="100%" height="100%" >
<mx:Spacer width="120"/>
<mx:Button label=" Save " id="saveBtn" click="saveToDb()" />
</mx:HBox>
You're creating the input components in ActionScript, but based on this code you are not creating them dynamically; you're just hard coding them. With your given sample, you'll know the components you are creating at compile time.
You'll need to store a reference to the form items you create; make them public variables instead of 'var' local variables. Kind of like this:
protected var ti:TextInput ;
protected var ta:TextArea ;
protected var df:DateField;
Then in your creation method, do something like this:
ti = new TextInput();
ti.id = Application.application.designList.getItemAt(i).component;
fm.addChild(ti);
ta = new TextArea();
ta.id = Application.application.designList.getItemAt(i).colName;
fm.addChild(ta);
df = new DateField();
df.id = Application.application.designList.getItemAt(i).component;
fm.addChild(df);
myform.addChild(fm);
Then when you need to access them, just do something like this:
private function getMyformData()
{
ti.text;
ta.text;
}
If you're generating the form components at run time based on data, then store then form elements in an array of some sort.
You could also work something out by looping over all children of your container, although that wouldn't be my first approach.
Since poster posted more complete code; here are some additions. I added the protected array of all form items and in each 'switch' block; the new input element is pushed onto the array.
<mx:Script>
protected var itemsArray : Array = new Array();
private function loadAllComponents():void
{
var formItemArray:Array = new Array();
for(var i:int=0; i< Application.application.designList.length; i++)//which had the colonName, colComponet to be dispalyed,
{
var fm:FormItem = new FormItem();
fm.label = Application.application.designList.getItemAt(i).colName;
var comp:String = Application.application.designList.getItemAt(i).component;
switch(comp)
{
case "TextBox":
var ti:TextInput = new TextInput();
ti.id = Application.application.designList.getItemAt(i).component;
fm.addChild(ti);
itemsArray.push(ti)
break;
case "TextArea":
var ta:TextArea = new TextArea();
ta.id = Application.application.designList.getItemAt(i).colName;
fm.addChild(ta);
itemsArray.push(ta)
break;
case "ComboBox":
var mycb:myComboBox = new myComboBox();
mycb.getAllMasterCBData(Application.application.selectedgridItem, Application.application.designList.getItemAt(i).colName);
fm.addChild(mycb);
itemsArray.push(mycb)
break;
case "DateField":
var df:DateField = new DateField();
df.id = Application.application.designList.getItemAt(i).component;
fm.addChild(df);
itemsArray.push(df)
break;
}
myform.addChild(fm);
}
}
The sateToDb method will change to be something like this:
private function saveToDb():void // Here i wan to read all the formdata
{
var formItems:Array = myform.getChildren();
for each (var item:UIComponent in itemsArray )
{
if (item is TextInput)
{
var text:String = Object(item).text;
Alert.show("came here");
}
else if (item is DateField)
{
var date:Date = DateField(item).selectedDate;
}
}
}
]]>
</mx:Script>
Edited Response:
OK, I think I see the issue.
You're adding your data controls to FormItems and adding those to the Form. But then you're iterating over the Form's children and as if they were the data controls and not FormItems.
Without commenting on the rest of the code, have a look at what this updated function is doing to retrieve the data controls:
private function saveToDb():void
{
var formItems:Array = myform.getChildren();
for each (var item:FormItem in formItems)
{
var itemChildren:Array = item.getChildren();
for each (var control:UIComponent in itemChildren)
{
if (control is TextInput)
{
var text:String = Object(item).text;
Alert.show("TextInput");
}
else if (control is DateField)
{
var date:Date = DateField(item).selectedDate;
Alert.show("Date");
}
}
}
You can delete the formItemArray variable too, it's not needed since we're getting the list of children from the Form and FormItems.
Original response:
If you keep a reference to each of the dynamic form items in an Array you can iterate over each of them in your getMyFormData() function.
e.g.
protected var formItems:Array = new Array();
// Other class stuff here...
var ti:TextInput = new TextInput();
ti.id = Application.application.designList.getItemAt(i).component;
formItems.push(ti); // Add item to array.
fm.addChild(ti);
var ta:TextArea = new TextArea();
ta.id = Application.application.designList.getItemAt(i).colName;
formItems.push(ta); // Add item to array.
fm.addChild(ta);
var df:DateField = new DateField();
df.id = Application.application.designList.getItemAt(i).component;
formItems.push(df); // Add item to array.
fm.addChild(df);
myform.addChild(fm);
<mx:button click="getMyformData()"/>
private function getMyformData()
{
//How to get the myform Data dynamically here after validations... ? &
for each (var item:UIComponent in formItems)
{
if (item is TextInput || item is TextArea)
{
// Cast to Object to access the 'text' property without the compiler complaining.
var text:String = Object(item).text;
// Do something with the text...
}
else if (item is DateField)
{
var date:Date = DateField(item).selectedDate;
// Do something with the date...
}
// Insert additional type checks as needed.
}
}
You'll have to work out what to do with the data on your own though :)
If you are using a separate list make sure you clear out the formItems array when you're done with it so you don't have references to the items keeping them in memory unnecessarily.
Instead of keeping a separate array of form items you could also iterate over the children in the fm container. You might have to make some assumptions about the children you'd be accessing but it looks like you have control over all of the children being added so that's no problem.
I hope that helps...
:)

moving between states I get an error in Flex

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
so i have a function that runs in state1 and has a
while(myCanvas.rawChildren.numChildren > 0){
myCanvas.rawChildren.removeChildAt(0);
}
//this code is definitely the problem....
I can move to state2, but when I move back to state1 i get the error.
why? the function that has the while loop only runs when something is searched in state1, so why is it running when coming back from state2?
edit...
so i did i test for a function that runs at app initialization:
private function init():void{
trace(g);
if(g == true){
while(myCanvas.rawChildren.numChildren > 0){
myCanvas.rawChildren.removeChildAt(0);
}
g = false;
}
trace(g);
}
It shouldnt run one it comes back to state1, but i still get the error. So basically as long as that while loop runs once while in state1 I can never get back to state1
<mx:states>
<mx:State name="contactform">
<mx:AddChild position="lastChild">
<mx:Canvas id="msgCanvas" backgroundColor="0xEEEEEE" height="121" y="158" width="800" fontWeight="normal" fontSize="12" backgroundAlpha="0.02" x="0">
</mx:Canvas>
</mx:AddChild>
<mx:AddChild position="lastChild">
<custom:email_cmp x="150" y="287" height="213"/>
</mx:AddChild>
</mx:State>
<mx:State name="main">
<mx:AddChild position="lastChild">
<mx:Canvas id="myCanvas" backgroundColor="0xEEEEEE" height="342" y="158" width="800" fontWeight="normal" fontSize="12" backgroundAlpha="0.02" x="0">
</mx:Canvas>
</mx:AddChild>
</mx:State>
</mx:states>
public function mainFunction():void{
origArray = [];
var cache:int = 0;
if(myCanvas.rawChildren.numChildren > 0){
myCanvas.rawChildren.removeChildAt(0);
}
//text format for links
var hFormat:TextFormat = new TextFormat();
hFormat.font = "Verdana";
hFormat.color = 0x000000;
hFormat.size = 15;
//text format end
var sprite1:Sprite = new Sprite();
var textQ:TextField = new TextField();
textQ.mouseEnabled = false;
if(amt_cnt.count == 1){
amt_cnt.end = amt_cnt.endCache;
amt_cnt.start = amt_cnt.startCache;
//set the text
textQ.defaultTextFormat = hFormat;
textQ.text = "Still can't find your answer? Need more help?";
textQ.x = 270;
textQ.y = 300;
textQ.width = textQ.textWidth +20;
textQ.selectable = false;
sprite1.addChild(textQ);
sprite1.buttonMode = true;
myCanvas.rawChildren.addChild(sprite1);
sprite1.addEventListener(MouseEvent.CLICK, moreHelp);
}else{
amt_cnt.end = amt_cnt.endCache;
amt_cnt.start = amt_cnt.startCache;
textQ.defaultTextFormat = hFormat;
textQ.text = "More Questions...";
textQ.x = 275;
textQ.y = 300;
textQ.width = textQ.textWidth +20;
textQ.selectable = false;
sprite1.addChild(textQ);
sprite1.buttonMode = true;
myCanvas.rawChildren.addChild(sprite1);
sprite1.addEventListener(MouseEvent.CLICK, moreQuestions);
}
var fontSize:int = 12;
//text formatting for the displayed question list Begin
var qFormat:TextFormat = new TextFormat();
qFormat.font = "Verdana";
qFormat.color = 0x000000;
qFormat.size = fontSize;
//ending text format
for(var t:uint = amt_cnt.start; t<amt_cnt.end; t++){
/*if(t == 0){
var topQ:TextField = new TextField();
topQ.text = full_array[t][1];
mainQsprite.addChild(topQ);
}*/
var qSprite:Sprite = new Sprite();
var txt:TextField = new TextField();
txt.defaultTextFormat = qFormat;
txt.text = full_array[t][0];
txt.selectable = false;
txt.mouseEnabled = false;
txt.border = false;
txt.width = 500; // how wide you want the text to go.
var numLines:Number = Math.floor(txt.textWidth/txt.width)+1; //calculates number of lines of the textfield.
txt.height = ((fontSize+8)*numLines);
txt.wordWrap = true;
qSprite.x = 30;
qSprite.y = 350;
qSprite.alpha = 0;
var temp_a:Number = cache; //20 is the padding between questions displayed
if(t != amt_cnt.end-1){
Tweener.addTween(qSprite, {y:temp_a, alpha:1, time:1, delay:t*0.1, transition:"easeoutexpo"}); //tweener INNNNN!
}else{
Tweener.addTween(qSprite, {y:temp_a, alpha:1, time:1, delay:t*0.1, transition:"easeoutexpo", onComplete:runTop}); //tweener INNNNN!
}
cache = txt.height + temp_a;
qSprite.buttonMode = true;
origArray[t] = new Array(qSprite.x,temp_a, qSprite);
mainDict[qSprite] = new Object();
mainDict[qSprite].question = full_array[t][0];
mainDict[qSprite].answer = full_array[t][1];
mainDict[qSprite].count = full_array[t][2];
mainDict[qSprite].top = full_array[t][3];
mainDict[qSprite].origX = qSprite.x;
mainDict[qSprite].origY = temp_a;
mainDict[qSprite].id = t;
mainDict[qSprite].height = txt.height;
amt_cnt[t] = new Object();
amt_cnt[t].hit = false;
qSprite.addChild(txt);
qSprite.addEventListener(MouseEvent.CLICK, clicked);
qSprite.addEventListener(MouseEvent.MOUSE_OVER, over);
qSprite.addEventListener(MouseEvent.MOUSE_OUT, out);
myCanvas.rawChildren.addChild(qSprite);
if(full_array[t][3] == true){
var thereIsTop:Boolean = true;
}
}
amt_cnt.array = origArray;
/*if(thereIsTop == true){
topAnswer(); //makes the top answer open first
thereIsTop = false;
}*/
}
So this the mainfunction. The top part has the states. main state is loaded first and has the myCanvas canvas. Everything in mainfunction adds to myCanvas.
This is my first time working with flex, so tell me if there is a better way of doing this.Thanks?
I really need to get this solved. I've been stressing over this for weeks.
I understand why you might not use mx:RemoveChild in your state (if you're managing your states in the easier-to-love mxml states property), but it looks like your code is trying to do what removeAllChildren() already does. Can you use removeAllChildren instead? Though, it would be nice to have more code to see what you're trying to accomplish.
Maybe you're handling an enterState event with this code ?

Disabling radiobuttongroup

Since Repeater component won't generate radiobuttongroup in mxml, and since I can't do the same through ActionScript because radiobuttongroup doesn't have an id property when I try to create it that way, is there a way to disable radiobuttons at all? As far as I can see, the only thing I can set and access is groupName property of radiobuttons.
For Repeater component I tried using xml directly
<mx:XML id="xquiz" source="quiz.xml" />
with this code:
<mx:Repeater dataProvider="{xquiz.question}" id="rep">
<mx:Label text="{rep.currentItem.content}" />
<mx:Repeater dataProvider="{rep.currentItem.answer}" id="rep2">
<mx:RadioButton label="{rep2.currentItem}" groupName="{'rbg'+rep.currentIndex}" click="checkAnswers(event)" value="{rep2.currentItem.#correct}" />
</mx:Repeater>
</mx:Repeater>
and cannot use repeater to generate radiobuttongroup since it's not a visible component.
I also tried ActionScript approach but with HTTPService mxml component to fetch xml file.
<mx:HTTPService id="srv" url="quiz.xml" resultFormat="e4x" result="handleResult(event);" fault="handleFault(event);"/>
and here's actionscript snippet:
private var xQuizData:XML
private function handleResult(event:ResultEvent):void {
xQuizData = event.result as XML;
initApp();
}
private function initApp():void {
var cnt:Number = 0;
for each (var question:XML in xQuizData.*) {
var lbl:Label = new Label();
lbl.text = question.content;
panel.addChild(lbl);
lbl.visible = true;
var cnt2:Number = 0;
for each (var answer:XML in question.answer) {
var rb:RadioButton = new RadioButton();
rb.id=String(cnt);
rb.label=answer;
rb.groupName="rbg"+String(cnt);
if (answer.hasOwnProperty("correct")) {
rb.value=true;
}
panel.addChild(rb);
rb.visible = true;
cnt2++;
}
cnt++;
}
}
I want to be able to catch clicks from radiobuttongroup controls, but can't get them to generate at all if with repeater or can't assign them id if with actionscript.
XML contents would look something like this:
<quiz>
<question>
<content>Some question?</content>
<answer>Answer one</answer>
<answer correct="true">Answer two</answer>
<answer>Answer three</answer>
<answer>Answer four</answer>
</question>
</quiz>
I'm having a hard time following what you are trying to do from your snippets, so here's a snippet of mine that should do exactly what your wanting. Hopefully you can review it and adapt it for your problem.
public function buildVBox():void{
tempVBox.removeAllChildren();
var iterator:Number = 0;
for each (var i:XML in myXML.children()){
var tempCanv:Canvas = new Canvas();
tempCanv.id = iterator.toString();
var tempRadYes:RadioButton = new RadioButton;
tempRadYes.x = 30;
tempRadYes.y = 20;
tempRadYes.origY = 20;
tempRadYes.groupName = "rbg" + iterator.toString();
tempRadYes.value = 1;
tempRadYes.label = "Yes"
tempCanv.addChild(tempRadYes);
var tempRadNo:extRadioButton = new extRadioButton;
tempRadNo.x = 80;
tempRadNo.y = 20;
tempRadNo.origY = 20;
tempRadNo.groupName = "rbg" + iterator.toString();
tempRadNo.value = 2;
tempRadNo.label = "No"
tempCanv.addChild(tempRadNo);
var tempRadNA:extRadioButton = new extRadioButton;
tempRadNA.x = 120;
tempRadNA.y = 20;
tempRadNA.origY = 20;
tempRadNA.groupName = "rbg" + iterator.toString();
tempRadNA.value = 0; tempRadNA.label = "N/A"
tempCanv.addChild(tempRadNA);
tempVBox.addChild(tempCanv);
iterator++;
}
}
Got a solution from here: http://www.jonathanrowny.com/journal/radiobuttongroup-inside-repeater

Resources