I'm just starting to learn flex and AS3
I'm trying to get information into a datagrid that originates from a mathmatical formula. For example if I have 100 and I subtract 5 from it and continue to do so until it reaches 0 so my grid would be something like:
100 | -5
95 | -5
90 | -5
...
...
5 | -5
0
I'm guessing that it needs to do something like this but can't find any examples of how to impliment something like this:
var i:Number = 100;
do {
add row to datagrid
i-5;
} while (i < 0);
Thanks
Dave
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var myDataProvider:ArrayCollection = new ArrayCollection();
private function onCreationComplete():void
{
var i:int = 100;
while(i >= 0) {
myDataProvider.addItem({"index" : i});
i -= 5;
}
}
]]>
</mx:Script>
<mx:DataGrid dataProvider="{ myDataProvider }" width="100%" height="100%">
<mx:columns>
<mx:DataGridColumn dataField="index" headerText="#"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Also take a look in Flex language reference DataGrid, there is example at the bottom of the page.
Related
I have a problem with the AdvancedDataGrid in Flex.
I have a AdvancedDataGrid with a Bindable ArrayCollection as DataProvider. When I set the ArrayCollection (by Clicking on Button 1) the AdvancedDataGrid will represent 4 Columns.
After that i click on Button 2. In this case the AdvancedDataGrid still shows 4 columns instead of the expected 3 columns.
Scenario 2
First clicked Button2 -> AdvancedDataGrid shows 3 columns
Clicking Button1 -> AdvancedDataGrid still shows 3 columns instead of the expected 4 columns
How can I tell the AdvancedDataGrid to adjust the Column count?
Snippet:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600" creationComplete="application1_creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var dataProv:ArrayCollection;
protected function button1_clickHandler(event:MouseEvent):void {
dataProv = new ArrayCollection([
{country:"USA", year2004:3.5, year2005:4.2, year2006:3.7},
{country:"UK", year2004:1.7, year2005:3.1, year2006:3.6},
{country:"Canada", year2004:2.8, year2005:2.9, year2006:3.4},
{country:"Japan", year2004:2.6, year2005:2.3, year2006:2.8},
{country:"France", year2004:1.4, year2005:2.1, year2006:2.6},
{country:"Brazil", year2004:2.6, year2005:4.9, year2006:4.4},
{country:"Russia", year2004:6.4, year2005:7.2, year2006:6.7},
{country:"India", year2004:8.0, year2005:7.1, year2006:6.6},
{country:"China", year2004:9.9, year2005:10.1, year2006:10.6}
]);
adg.validateNow();
adg.dataProvider.refresh();
}
protected function button2_clickHandler(event:MouseEvent):void{
dataProv = new ArrayCollection([
{country:"USA", year2004:3.5, year2005:4.2},
{country:"UK", year2004:1.7, year2005:3.1},
{country:"Canada", year2004:2.8, year2005:2.9},
{country:"Japan", year2004:2.6, year2005:2.3},
{country:"France", year2004:1.4, year2005:2.1},
{country:"Brazil", year2004:2.6, year2005:4.9},
{country:"Russia", year2004:6.4, year2005:7.2},
{country:"India", year2004:8.0, year2005:7.1},
{country:"China", year2004:9.9, year2005:10.1}
]);
adg.validateNow();
adg.dataProvider.refresh();
}
]]>
</mx:Script>
<mx:HBox width="100%" height="100%">
<mx:AdvancedDataGrid
id="adg"
width="100%"
height="100%"
dataProvider="{dataProv}"/>
<mx:Button label="change" click="button1_clickHandler(event)"/>
<mx:Button label="changeBack" click="button2_clickHandler(event)"/>
</mx:HBox>
</mx:Application>
You need to extend the AdvancedDataGrid class and override the collectionChangeHandler. You need to set the protected var generatedColumns to true in order for the dynamic column code to execute more than once.
override protected function collectionChangeHandler(event:Event):void
{
generatedColumns = true;
super.collectionChangeHandler(event);
}
in FlashBuilder I want to dynamically generate approximately 1200 rectangles from a CSV file (these are all different colours) which will perform an action on Click.
What is the best way to go about doing this? I've read that the drawing API on Air and Android is not a good idea, and am thinking about using the Spark Rectangle class, but I can't seem to work out how to apply a colour to it if I'm generating them dynamically using AS?
After reading in your CSV, loop through the elements and call a function something like so:
private function addRect(color:uint, xPos:Number, yPos:Number, width:Number, height:Number):void {
var rect:Rect = new Rect();
rect.x = xPos;
rect.y = yPos;
rect.width = width;
rect.height = height;
var fillColor:SolidColor = new SolidColor(color);
rect.fill = fillColor;
var obj:Group = new Group();
obj.addElement(rect);
obj.addEventListener(MouseEvent.CLICK, this.onClick);
this.addElement(obj);
}
private function onClick(e:Event):void {
trace("clicked");
}
Hope that helps.
You can do the entire UI declaratively. Parse the CSV into data structures, and pop it into an ArrayCollection. In this example, I just threw together three samples.
Then, create a DataGroup and set the dataProvider="rectangles" and then create an itemRenderer.
This example works well, IMO:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
var rectangles:ArrayCollection = new ArrayCollection([
{color: 0x00FF00, x: 5, y: 10, width: 30, height: 40},
{color: 0xFF0000, x: 50, y: 100, width: 300, height: 400},
{color: 0x0000FF, x: 55, y: 10, width: 30, height: 40},
]);
]]>
</fx:Script>
<s:DataGroup dataProvider="{rectangles}" itemRenderer="RectangleRenderer" />
</s:Application>
Then, the itemRenderer looks like this:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true"
click="whenClicked()"
x="{data.x}" y="{data.y}"
width="{data.width}" height="{data.height}">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private function whenClicked():void {
Alert.show("clicked");
}
]]>
</fx:Script>
<s:Rect width="100%" height="100%">
<s:fill>
<s:SolidColor color="{data.color}" />
</s:fill>
</s:Rect>
</s:ItemRenderer>
I create an HBox, fill it with a grid of buttons, and set the scroll policy. When I resize the window, the stage changes size, and so does the HBox ... to a point. Once it reaches the height of the Grid it contains, it stops shrinking, like it has a "min-height". This ruins the scrollbar that I'm trying to establish in this case.
I've set the height to 100%, shouldn't it always take the height of the stage, its parent?
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init();" horizontalScrollPolicy="off" verticalScrollPolicy="off" width="100%">
<mx:Script>
<![CDATA[
import mx.controls.Button;
import mx.containers.Grid;
import mx.containers.GridRow;
import mx.containers.GridItem;
protected function init():void {
for (var i:int = 0; i < 3; i++) {
var gRow:GridRow = new GridRow();
gRow.percentWidth = 100;
gRow.height = 100;
var gItem:GridItem = new GridItem();
gItem.percentWidth = 100;
var btn:Button = new Button();
btn.label = "BUTTON";
btn.percentWidth = 100;
btn.percentHeight = 100;
gItem.addChild(btn);
gRow.addChild(gItem);
mainGrid.addChild(gRow);
}
}
]]>
</mx:Script>
<mx:HBox width="100%" height="100%" horizontalScrollPolicy="off" verticalScrollPolicy="on" id="main" clipContent = "true">
<mx:Grid id="mainGrid" width="100%" height="100%" />
</mx:HBox>
</mx:Application>
So it looks like I managed to mention the eventual answer in my question. It's the "minHeight" property folks, looks like it gets set to the contained grids height, and will shrink no smaller. Set it to 0, and your good to go.
I hope this dialog I'm having with myself helps someone else. :)
you can try to give it the heigh of the HBox, as height="{hb.height}" ,hb as id
I have prepared a simple test case for a PopUpButton opening a TileList with black and red entries and it mostly works, but has 2 annoyances.
I've searched a lot, tried several variants (added [Bindable] members in my renderer; added color member to the bids array; created my public override set data() method; ...) and has been getting some answers too, but they are way too general.
I would appreciate if someone can suggest code to fix the 2 issues in my code:
1) Scrolling "tl2" right-left doesn't work well: the entries are displayed in a mix of red and black. I know the TileList reuses itemRenderer, but how do I fix the problem?
2) In debug-mode I get numerous warnings:
warning: unable to bind to property 'label' on class 'Object' (class is not an IEventDispatcher)
Thank you,
Alex
MyRenderer.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
width="100%" height="100%">
<mx:Script>
<![CDATA[
public static function findColor(str:String):uint {
return (str.indexOf('♥') != -1 ||
str.indexOf('♦') != -1) ? 0xFF0000 : 0x000000;
}
]]>
</mx:Script>
<mx:Label truncateToFit="true" width="60"
text="{data.label}" color="{findColor(data.label)}"/>
</mx:Canvas>
MyTest.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationPolicy="all" applicationComplete="init(event);">
<mx:Style>
#font-face {
src:url("C:\\WINDOWS\\Fonts\\arial.ttf");
fontFamily: myFont;
unicodeRange:
U+0020-U+0040, /* Punctuation, Numbers */
U+0041-U+005A, /* Upper-Case A-Z */
U+005B-U+0060, /* Punctuation and Symbols */
U+0061-U+007A, /* Lower-Case a-z */
U+007B-U+007E, /* Punctuation and Symbols */
U+0410-U+0451, /* cyrillic */
U+2660-U+266B; /* card suits */
}
List, CheckBox, Label, Button, PopUpButton, TileList {
fontFamily: myFont;
fontSize: 24;
}
</mx:Style>
<mx:Script>
<![CDATA[
import mx.controls.*;
import mx.events.*;
[Bindable]
private var bids:Array;
private var tl:TileList;
private function init(event:FlexEvent):void {
bids = createBids();
pub.popUp = createList(bids);
}
private function createBids():Array {
var arr:Array = [{label: 'Pass'}];
for (var i:uint = 6; i <= 10; i++)
for (var j:uint = 0; j < 5; j++)
arr.unshift({label: i+'♠♣♦♥ '.charAt(j%5)});
return arr;
}
private function createList(arr:Array):TileList {
tl = new TileList();
tl.maxColumns = 5;
tl.width = 350;
tl.height = 250;
tl.dataProvider = arr;
tl.itemRenderer = new ClassFactory(MyRenderer);
tl.addEventListener('itemClick', itemClickHandler);
if (arr.length > 0) {
tl.selectedIndex = arr.length - 1;
pub.label = arr[tl.selectedIndex].label;
}
return tl;
}
private function itemClickHandler(event:ListEvent):void {
var index:uint = tl.columnCount * event.rowIndex + event.columnIndex;
var label:String = bids[index].label;
pub.label = label;
pub.setStyle('color', MyRenderer.findColor(label));
pub.close();
tl.selectedIndex = index;
}
]]>
</mx:Script>
<mx:Panel title="TileList scrolling problem" height="100%" width="100%"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
<mx:Label width="100%" color="blue" text="Select your bid:"/>
<mx:TileList id="tl2" height="200" width="200"
maxColumns="5" rowHeight="30" columnWidth="60"
dataProvider="{bids}" itemRenderer="MyRenderer"/>
</mx:Panel>
<mx:ApplicationControlBar width="100%">
<mx:Spacer width="100%"/>
<mx:CheckBox id="auto" label="Auto:"/>
<mx:Button id="left" label="<<"/>
<mx:PopUpButton id="pub" width="90"/>
<mx:Button id="right" label=">>"/>
</mx:ApplicationControlBar>
</mx:Application>
Update:
Thank you Wade, the warning is gone now (I guess it was not ok to use {data.label} in my label), but the "tl2" still has scrolling issues.
New MyRenderer.mxml (still has scrolling issues):
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
width="100%" height="100%">
<mx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
var str:String = String(value.label);
myLabel.text = str;
myLabel.setStyle('color', findColor(str));
}
public static function findColor(str:String):uint {
return (str.indexOf('♥') != -1 ||
str.indexOf('♦') != -1) ? 0xFF0000 : 0x000000;
}
]]>
</mx:Script>
<mx:Label id="myLabel" truncateToFit="true" width="60"/>
</mx:Canvas>
You can take care of both of your issues by overriding the set data method on your item renderer:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
width="100%" height="100%">
<mx:Script>
<![CDATA[
override public function set data(value:Object):void {
super.data = value;
var str:String = value.label;
this.myLabel.text = str;
this.myLabel.setStyle("color", (str.indexOf('♥') != -1 ||
str.indexOf('♦') != -1) ? 0xFF0000 : 0x000000);
}
]]>
</mx:Script>
<mx:Label id="myLabel" truncateToFit="true" width="60"/>
</mx:Canvas>
Since the renderers are re-used, the best way to ensure they are correctly updated is to use the set data method since it always gets called when a renderer gets re-used. This also gets rid of your binding warning since you are no longer binding to data.label. Note: I haven't tested this code, it may need some tweaking :) Hope that helps.
EDIT: Your "tl2" issue looks like it's caused by horizontally scrolling your tile list, whereas the TileList appears to be optimized for vertical scrolling. Since your data set is finite and relatively small, I would make the tile list full size to show all of the elements (eliminating item renderer re-use) and wrap it in a canvas set to the desired dimensions and let the canvas handle the scrolling. Probably not the answer you are looking for, sorry.
First of all I know there is a spark VolumeBar component but, for design requirements I can't use it..
I'm trying to create a custom component but heights are not responding as should
[Update]
This is were I call the class
<components:VolumeSlider steps="4" height="100" />
The problem is that the volume slider is adapting perfectly, but My custom items component doesn't.
<s:HGroup width="100%" height="100%" maxHeight="{height}" >
<s:VGroup width="100%" height="100%" paddingBottom="20" paddingTop="20">
<s:VSlider id="slider" width="100%" height="100%" maximum="{_steps-1}" />
</s:VGroup>
<s:VGroup id="items" width="100%" height="100%" />
</s:HGroup>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
private var _steps:uint = 10;
public function set steps( value:uint ):void
{
_steps = value;
if ( items != null && items.numChildren != 0 )
{
items.removeAllElements();
}
create();
}
private function create():void
{
for ( var i:uint = 0; i < _steps; ++i )
{
var item:VolumeSliderItem = new VolumeSliderItem();
item.percentHeight = item.percentWidth = 100;
if ( items != null )items.addElement(item );
}
}
]]>
</fx:Script>
where VolumeSliderItem is a spark button
I don't see any call to create(). I added 'creationComplete="create()"' on the Application tag, and then it created 10 sliders to the VGroup with id 'items'. Is that what you're looking for?