Flex图表操作与单元测试全解析
立即解锁
发布时间: 2025-08-18 00:51:44 阅读量: 7 订阅数: 9 


Flex 4 Cookbook:实用编程指南
### Flex 图表操作与单元测试全解析
#### 1. 图表项目外观定制
在处理图表时,有时需要改变图表中项目的外观,也就是进行皮肤定制。
##### 问题描述
需要改变图表中显示项目的外观。
##### 解决方案
创建一个继承自 `ProgrammaticSkin` 类并实现 `IDataRenderer` 接口的类,然后将该皮肤类设置为图表 `ChartSeries` 的 `itemRenderer`。
##### 详细讨论
`mx.charts.ChartItem` 代表系列中的一个数据点,系列的 `dataProvider` 中的每个项目都对应一个 `ChartItem`。`ChartItem` 定义了以下属性:
| 属性 | 描述 |
| ---- | ---- |
| `currentState` | `ChartItem` 的外观 |
| `element` | 拥有 `ChartItem` 的系列或元素 |
| `index` | `ChartItem` 所代表的系列 `dataProvider` 中数据的索引 |
| `item` | `ChartItem` 所代表的系列 `dataProvider` 中的项目 |
| `itemRenderer` | 表示此 `ChartItem` 的图表项目渲染器的实例 |
不同类型的图表有不同的默认渲染器,如下表所示:
| 图表类型 | 渲染器类 |
| ---- | ---- |
| `AreaChart` | `AreaRenderer` |
| `BarChart` | `BoxItemRenderer` |
| `BubbleChart` | `CircleItemRenderer` |
| `ColumnChart` | `CrossItemRenderer` |
| `PlotChart` | `DiamondItemRenderer`、`ShadowBoxRenderer`、`TriangleItemRenderer` |
| `CandlestickChart` | `CandlestickItemRenderer` |
| `HLOCChart` | `HLOCItemRenderer` |
| `LineChart` | `LineRenderer`、`ShadowLineRenderer` |
| `PieChart` | `WedgeItemRenderer` |
要将图像设置为图表系列的 `itemRenderer`,只需将嵌入的图像设置为 `itemRenderer` 属性值,示例代码如下:
```xml
<mx:PlotSeries xField="goals" yField="games" displayName="Goals per game"
itemRenderer="@Embed(source='../assets/soccerball.png')"
radius="20"
legendMarkerRenderer="@Embed(source='../assets/soccerball.png')"/>
```
若要为图表项目创建皮肤,可创建一个 `ProgrammaticSkin` 并覆盖 `updateDisplayList()` 方法,示例代码如下:
```actionscript
package oreilly.cookbook
{
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.IBitmapDrawable;
import mx.charts.series.items.ColumnSeriesItem;
import mx.core.IDataRenderer;
import mx.skins.ProgrammaticSkin;
public class CustomRenderer extends ProgrammaticSkin implements IDataRenderer {
private var _chartItem:ColumnSeriesItem;
[Embed(source="assets/Shakey.png")]
private var img:Class;
public function get data():Object {
return _chartItem;
}
public function set data(value:Object):void {
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function updateDisplayList(
unscaledWidth:Number,unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
var img_inst = new img();
var bmd:BitmapData = new BitmapData((img_inst as DisplayObject).height,
(img_inst as DisplayObject).width, true);
bmd.draw(img_inst as IBitmapDrawable);
graphics.clear();
graphics.beginBitmapFill(bmd);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
}
}
```
然后将 `CustomRenderer` 设置为 `ColumnSeries` 的 `itemRenderer`,示例代码如下:
```xml
<mx:ColumnChart id="column" dataProvider="{expenses}">
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}"
categoryField="Month" />
</mx:horizontalAxis>
<mx:series>
<mx:Array>
<mx:ColumnSeries xField="Month"
yField="Expenses"
displayName="Expenses"
itemRenderer="oreilly.cookbook.CustomRenderer" />
</mx:Array>
</mx:series>
</mx:ColumnChart>
```
#### 2. 动态添加和移除图表列
在运行时,可能需要添加或移除图表中的数据列。
##### 问题描述
需要在运行时添加或移除图表中的数据列。
##### 解决方案
使用 ActionScript 创建 `ColumnSet` 并添加或移除 `ColumnSeries` 对象。
##### 详细讨论
`ColumnSet` 允许在图表中添加或移除多个 `ColumnSeries` 对象。不同的图表类型有不同的集合类型,例如 `ColumnChart` 使用 `ColumnSet` 来分组多个 `ColumnSeries` 实例。系列实例使用 `type` 属性来确定系列项目的分组方式,如下表所示:
| 属性 | 描述 |
| ---- | ---- |
| `clustered` | 系列项目在每个类别中并排分组,这是 `BarCharts` 和 `ColumnCharts` 的默认方式 |
| `stacked` | 系列项目相互堆叠,每个项目代表其下方项目的累积值 |
| `overlaid` | 系列项目相互叠加,最后一个项目在最上面 |
| `100%` | 系列项目相互堆叠,每个项目代表其在整个集合中的百分比值,总和为 100% |
以下是一个示例,使用一个数据集来跟踪一周内每天的降雨量。每个时间段是一个系列,并在 ActionScript 中初始化。对于每个系列,都有一个复选框,当复选框的值更改时,`ColumnSet` 会重新初始化,并为每个选中的复选框添加一个系列,最后将 `ColumnSet` 添加到一个新数组中并设置为 `ColumnChart` 的 `series` 属性,示例代码如下:
```xml
<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"
backgroundColor="0xFFFFFF" creationComplete="onComplete()">
<s:layout><s:HorizontalLayout/></s:layout>
<fx:Script>
<![CDATA[
import mx.charts.series.ColumnSet;
import mx.charts.series.ColumnSeries;
[Bindable] private var chartDP:Array = [{day:'Monday',dawnRainfall:10,
morningRainfall:12,midDayRainfall:6,afternoonRainfall:4,
duskRainfall:5},{day:'Tuesday',dawnRainfall:7,morningRainfall:10,
midDayRainfall:5,afternoonRainfall:5,duskRainfall:6},
{day:'Wednesday',dawnRainfall:5,morningRainfall:9,
midDayRainfall:3,afternoonRainfall:2,duskRainfall:3},
{day:'Thursday',dawnRainfall:8,morningRainfall:9,
midDayRainfall:6,afternoonRainfall:6,duskRainfall:6},
{day:'Friday',dawnRainfall:11,morningRainfall:13,
midDayRainfall:4,afternoonRainfall:5,duskRainfall:7},
{day:'Saturday',dawnRainfall:12,morningRainfall:13,
midDayRainfall:9,afternoonRainfall:3,duskRainfall:4},
{day:'Sunday',dawnRainfall:14,morningRainfall:12,
midDayRainfall:5,afternoonRainfall:1,duskRainfall:3}
];
private var dawnSeries:ColumnSeries;
private var morningSeries:ColumnSeries;
private var midDaySeries:ColumnSeries;
private var afternoonSeries:ColumnSeries;
private var duskSeries:ColumnSeries;
private var columnSet:ColumnSet;
private function onComplete():void
{
// initialize our clustered ColumnSet
columnSet = new ColumnSet();
columnSet.type = "clustered";
// initialize all of our series
dawnSeries = new ColumnSeries();
dawnSeries.yField = "dawnRainfall";
dawnSeries.xField = "day";
dawnSeries.displayName = "Dawn Rainfall";
morningSeries = new ColumnSeries();
morningSeries.yField = "morningRainfall";
morningSeries.xField = "day";
morningSeries.displayName = "Morning Rainfall";
midDaySeries = new ColumnSeries();
midDaySeries.yField = "midDayRainfall";
midDaySeries.xField = "day";
midDaySeries.displayName = "Mid-day Rainfall";
afternoonSeries = new ColumnSeries();
afternoonSeries.yField = "afternoonRainfall";
afternoonSeries.xField = "day";
afternoonSeries.displayName = "Afternoon Rainfall";
duskSeries = new ColumnSeries();
duskSeries.yField = "duskRainfall";
duskSeries.xField = "day";
duskSeries.displayName
```
0
0
复制全文
相关推荐










