Is it possible to stop my labels disappearing on my flex pie chart between segment selections whilst interpolating? - apache-flex

I have a flex pie chart:
<mx:PieChart alpha="0.9" fontSize="{QPieSeries_font}" width="100%" top="20" height="320" id="QPieChart"
dataProvider="{dataObj}" horizontalCenter="0" color="0xFFFFFF" fontFamily="MyriadWebPro"
showDataTips="true" dataTipFunction="QdataTipFunction"
dataTipItemsSet="true" itemClick="QPieChart_itemClickHandler(event)">
<mx:series>
<mx:PieSeries id="QPieSeries" labelField="Answer" field="Value" labelPosition="callout"
showDataEffect="QSeriesInterpolate" alpha="1"
reserveExplodeRadius="0.05"/>
</mx:series>
</mx:PieChart>
where the QSeriesInterpolate is a simple interpolation given in the declaration:
<fx:Declarations>
<mx:SeriesInterpolate id="QSeriesInterpolate" duration="500" />
</fx:Declarations>
and the item click event looks like:
protected function QPieChart_itemClickHandler(event:ChartItemEvent):void
{
var ExAr:Array = [];
ExAr[event.hitData.chartItem.index] = 0.05;
QPieSeries.perWedgeExplodeRadius = ExAr;
}
Basically, what annoys me is that when I click a segment to activate the interpolated event, the datatips disappear for it's duration. Whilst this is only half a second, it still detracts from user experience. Is there anything I can do to avoid it??
ALSO! Another thing: Is it obvious to anyone why my dataTipFunction doesnt work? It looks as follows:
public function QdataTipFunction(hitData:HitData):String
{
var a:String = "abc"
return a;
}
Yes it's simple but I was just trying to persuade it to work... to no avail. I think it might be some sort of font issue?
Thanks!
Josh

You might consider looking into Axiis. It is a flex data visualization framework, and has some awesome example charts. The main deal though is you have full control over EVERTHING! Probably overkill for what you are doing, but it really is awesome.
http://www.axiis.org/examples.html

Related

Flex DividedBox children are displayed outside

I am using a DividedBox in Flex which contains only a datagrid at first. When I click on an Item on the Datagrid, a second element with a width of 0% (Spark Group) is added to the divided box to display an image.
The thing is, when the second element is added to the DividedBox, the image is partially displayed outside the DividedBox, and I don't want to have this behavior.
Here is the interesting code :
<mx:DividedBox direction="horizontal" id="divider" borderColor="red" borderStyle="solid" borderVisible="true" right="10" left="10" top="10" bottom="10">
<s:Group width="100%" height="100%">
<!--datagrid-->
</s:Group>
</mx:DividedBox>
And here is the piece of code that adds the second child of the dividedBox (simplified code) :
private var _pdf_preview:Group = new Group();
[Bindable]
[Embed(source="assets/image/llama.jpg")]
private var imgClass:Class;
protected function itemOnClickHandler(event:MouseEvent):void
{
_pdf_preview = new Group();
var img:Image = new Image();
img.source = imgClass;
_pdf_preview.addElement(img);
_pdf_preview.percentWidth = 0;
divider.addElement(_pdf_preview);
}
And here is a screen of the problem (Btw, don't notice my skills on Gimp :) ). As a new user I can't bind images to my post : screen showing my problem the red border show the limits of the dividedBox
Thank you.
I hope there are not too much fault, english is not my native language. Sorry for any english mistakes.
PS : I couldn't add the "DividedBox" tags because it was not existing before, and I'm a "new user" so I can't create new tags.
You can use the clipContent property to cut off the image at the edge of the DividedBox:
<mx:DividedBox clipContent="true" />
When using Spark containers, clipAndEnableScrolling is the property you need to achieve the same goal.
I would also like to note that you usually don't require to dynamically add components through ActionScript. You can use 'states' instead. For example:
<s:states>
<s:State name="normal" />
<s:State name="image" />
</s:states>
<mx:DividedBox clipContent="true">
<s:DataGrid />
<s:Image includeIn="image" />
</mx:DividedBox>
Now all you need to do to show the Image, is set the currentState to image.

mx.chart.AxisRenderer labelRotation not working

I'm attempting to rotate the category labels on my flex chart, but the labelRotation property seems to not work. Based on examples and the livedocs, I can't seem to figure out what I'm doing wrong.
<mx:BarChart id="barchartX" left="40" right="40" bottom="40" paddingBottom="40"
dataProvider="{chartDataObj.series}" showDataTips="false"
itemClick="editItem_clickHandler(event)" includeIn="BAR" visible="true">
<mx:verticalAxis>
<mx:CategoryAxis id="vaxis" categoryField="title"
title="click here to rename this axis" />
</mx:verticalAxis>
<mx:verticalAxisRenderers>
<mx:AxisRenderer axis="{vaxis}" labelRotation="45"
click="axis_clickHandler(event)"/>
</mx:verticalAxisRenderers>
<mx:horizontalAxis>
<mx:LinearAxis id="haxis" title="click here to rename this axis" />
</mx:horizontalAxis>
<mx:horizontalAxisRenderers>
<mx:AxisRenderer axis="{haxis}" labelRotation="0"
click="axis_clickHandler(event)"/>
</mx:horizontalAxisRenderers>
<mx:series>
<mx:BarSeries labelPosition="none" yField="title" xField="value"
fills="{chartDataObj.colors}"/>
</mx:series>
I am including my answer to a similar question, https://stackoverflow.com/a/9129992/892191
The key to making the labelRotation work is embedding of fonts.
There is a good article on Flex 4.6 here
A simple code example would be to add a style to the mxml file,
<fx:Style>
#namespace mx "library://ns.adobe.com/flex/mx";
#font-face{
src: local("Arial");
fontFamily: Arial;
embedAsCFF: false;
}
mx|ColumnChart {
fontFamily: Arial;
fontSize: 10;
}
</fx:Style>
Okay, after searching through the actual code of the AxisRenderer I came up with this:
<fx:Script>
[Embed(source='../assets/verdana.ttf',
fontName='verdanaFontMX',
mimeType='application/x-font',
embedAsCFF='false')]
private var font2:Class;
</fx:Script>
<mx:verticalAxisRenderers>
<mx:AxisRenderer axis="{vaxis}" labelRotation="90"
labelClass="mx.controls.Label"
fontFamily="verdanaFontMX" canStagger="false"
click="axis_clickHandler(event)"/>
</mx:verticalAxisRenderers>
When using a CategoryAxis for an MX chart in a mobile project, the category labels are rendered as Spark Labels, but the rest of the axis labels are rendered as MX Labels. The label rotation works, but a warning is thrown and the category is rendered using the device font instead. To fix this, use the MX Label class instead (labelClass="mx.controls.Label"). I know it doesn't render quickly as the Spark label, but it will render in the font you want.
Next, if you have a category label that's very long, somehow there is division by zero and the whole thing crashes. To avoid this, set canStagger="false" or canDropLabels="true". This avoids whatever measurement errors were happening. However, if the fontSize is set, and the label ends up being too large, the automatic sizing crashes again. So, I guess the easiest solution would be to keep the category labels short.
There is also the possibility of truncating the text as found here: http://help.adobe.com/en_US/flex/using/WS02f7d8d4857b1677355f601a126b41ed60e-8000.html
or, using a custom labelRenderer, but this can get very involved and can have diminishing returns on the amount of work versus the benefit to the look.

How can I add multiple icons to the Spark TabBar control?

In the MX TabBar component, the iconField property allowed us to display different icons in each tab. In Spark, there does not seem to be an inherent way to add icons to the TabBar. Does anyone have an example of implementing icon support for Spark's TabBar? Is there a way to do this without extending the component?
Many thanks!
Hey after spending a week trying to follow multiple ways, (yours being top of the list) i found out a simpler and effective way to add icons to my tab bar, or any other component using skinning.
You dont need to create a custom component, just passing the icon and label through data.
http://cookbooks.adobe.com/post_Tutorials_for_skinning_Spark_ButtonBar_component_w-16722.html
As personally, i was using content navigator with my tabbar/viewstack, i passed the icon as icon instead of imageicon. you can make changes accordingly.
You'll have to create a skin for adding icons to Spark components; it is not as straightforward (IMHO) as Flex 3's MX components, though much more extensible.
Here are a few links which might help you get started:
Tour de Flex Tabbar examples
Custom Skin on Tabbar
Flex Tabbar with Skin
I believe I've come up with a solution, which I'm posting below for posterity. If anyone has a better way, I'd much appreciate the suggestion.
<!-- main app: TabBar implementation -->
<s:TabBar
dataProvider="{contentTabBarPrimaryDP}"
skinClass="skins.ContentTabBarSkin"/>
<!-- skins.ContentTabBarSkin: ItemRenderer implementation -->
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<custom:IconButtonBarButton
label="{data.label}"
icon="{data.icon}"
skinClass="skins.ContentTabBarButtonSkin"/>
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
<!-- skins.ContentTabBarButtonSkin: icon implementation -->
<s:HGroup
gap="3"
paddingBottom="3"
paddingLeft="3"
paddingRight="3"
paddingTop="3"
verticalAlign="middle">
<!--- layer 2: icon -->
<s:BitmapImage id="iconDisplay"
left="5"
verticalCenter="0" />
<!--- layer 3: label -->
<s:Label id="labelDisplay"
textAlign="center"
verticalAlign="middle"
maxDisplayedLines="1"
horizontalCenter="0" verticalCenter="1"
left="10"
right="10"
top="2"
bottom="2">
</s:Label>
</s:HGroup>
This solution uses a custom DTO object for the TabBar dataProvider which stores the label text as well as the embedded icon image as a class. I also had to extend the ButtonBarButton component to add an iconDisplay SkinPart, which looks like this:
[SkinPart(required="false")]
public var iconDisplay:BitmapImage;
This class also has getters/setters for the icon class property and sets the icon source, as such:
public function set icon(value:Class):void {
_icon = value;
if (iconDisplay != null)
iconDisplay.source = _icon;
}
override protected function partAdded(partName:String, instance:Object):void {
super.partAdded(partName, instance);
if (icon !== null && instance == iconDisplay)
iconDisplay.source = icon;
}
It's seems to be a bug/missed functionality of the your SDK version:
http://forums.adobe.com/thread/552543
http://bugs.adobe.com/jira/browse/SDK-24331
Anyway, thanks for the solution with skins - very helpful

sequencing through several images

I'm using flex and have a few images that I need to sequence through. I may add some text under each image. What I'm trying to do is automatically sequence through these images such that a black fading effect appears briefly between each image and the next - sure you've seen that sort of thing before.
My questions are this:
should these images be considered as states of a component or what? I was going to go that way, but corrections are welcome
how to get that black fading effect between the images and the next. Any clues please
Update: found an example of it. This example has more elements, but the idea is the same, an images fades and another images loads.
http://www.lifeblue.com/flash/lb_banner.swf
You can try using a ViewStack and a Timer to iterate through its children. Just add a fade in/fade out effect on them and you'll get what you're looking for.
Something like that :
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="black" creationComplete="creationCompleteHandler">
<mx:Script>
<![CDATA[
private var timer:Timer;
private function creationCompleteHandler():void
{
timer = new Timer( 2000 );
timer.addEventListener( TimerEvent.TIMER, timerHandler );
timer.start();
}
private function timerHandler( e:TimerEvent ):void
{
if( vs.selectedIndex == vs.getChildren().length - 1 )
vs.selectedIndex = 0;
else
vs.selectedIndex++;
}
]]>
</mx:Script>
<mx:Fade id="fadeIn" alphaFrom="0" alphaTo="1" duration="500" effectEnd="timer.start();"/>
<mx:Fade id="fadeOut" alphaFrom="1" alphaTo="0" duration="500" effectEnd="timer.stop();"/>
<mx:ViewStack id="vs">
<mx:Canvas showEffect="fadeIn" hideEffect="fadeOut">
<mx:Image source="picture1.jpg"/>
</mx:Canvas>
<mx:Canvas showEffect="fadeIn" hideEffect="fadeOut">
<mx:Image source="picture2.jpg"/>
</mx:Canvas>
<mx:Canvas showEffect="fadeIn" hideEffect="fadeOut">
<mx:Image source="picture3.jpg"/>
</mx:Canvas>
</mx:ViewStack>
</mx:Application>
Note that this code isn't the most optimized one. The best would be to create a custom component with a black background and 2 Image components.
Set the alpha property of both of
them to 0
Load a picture in the first one, then
play your fade in effect
Begin to load the following picture
in the second Image component
Fade out the first one, fade in the
second, and load the following
picture in the first Image, etc.
This way you only got one Container (instead of one per picture plus the ViewStack) and 2 Images.
It will also be easier to clean them from memory if you need to.

Flex: Scrolling in datagrids

I have 2 questions about flex datagrids:
How can I scroll it automatically to the bottom when new portion of data arrived to it (e.g. I added new items)
Strange, but seems it doesn't scroll when I use scrolling wheel, is there any trick about it (especially for mac Users)
Thanks in advance
Some changes:
public function scroll():void
{
trace(chatboard.maxVerticalScrollPosition);
chatboard.verticalScrollPosition = chatboard.maxVerticalScrollPosition;
}
<mx:TextArea id="chatboard" x="10" y="10" width="310" height="181" text="{chatMessages}" editable="false" verticalScrollPolicy="on" resize="scroll()"/>
But actually it don't help. The text area is not autoscrolled :(
Seems that 1) scroll is not called after new string is added to chatMessages
I find here that the mouse wheel scrolls the text area by default. Are you looking for a different behavior?
As far as skipping to the end goes:
in your TextArea wire up to the updateComplete and it seems to work as you would like:
<mx:TextArea id="textArea1" liveScrolling="true" updateComplete="textArea1_Changed(event);" />
then
private function textArea1_Changed(event:Event):void {textArea1.verticalScrollPosition = textArea1.maxVerticalScrollPosition;}
finally, you can test with something like:
private function btnClick(e:Event):void{textArea1.text += new Date().getTime().toString() + "\n";}
1) dataGrid.verticalScrollPosition=dataGrid.maxVerticalScrollPosition

Resources