ColumnChart数据源只有一个数据时出现“无法访问空对象引用的属性或方法”解决方法...

NPE in AxisRenderer when stacked column chart has one data item

错误信息:
I have been unable to create a simple test-case that reproduces this error, but I think a code inspection shows a problem. I've also been unable to get any help with a workaround on the Adobe forums or flexcoders.
The error is a null pointer exception when a stacked column chart has a single data item.

In AxisRenderer.as (line 2200 in sdk3.3) we find a reference to "lastLabel" which will be null if there is only one label, because it is computed as _labels[1].


Excerpt from AxisRenderer.calcStaggeredSpacing:



lastLabel = _labels[1];



if (adjustable.left == false)
{
staggeredScale = Math.min(
staggeredScale,
staggeredleftGutter / (firstLabel.width / 2));
}



if (adjustable.right == false)
{
staggeredScale = Math.min(
staggeredScale,
staggeredrightGutter / (lastLabel.width / 2)); // (me) Here's where the NPE occurs.
}



Stack Crawl:

__________



TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.charts::AxisRenderer/calcStaggeredSpacing()[C:\work\flex\dmv_automation\proj ects\datavisualisation\src\mx\charts\AxisRenderer.as:2200]
at mx.charts::AxisRenderer/calcRotationAndSpacing()[C:\work\flex\dmv_automation\pr ojects\datavisualisation\src\mx\charts\AxisRenderer.as:1591]
at mx.charts::AxisRenderer/adjustGutters()[C:\work\flex\dmv_automation\projects\da tavisualisation\src\mx\charts\AxisRenderer.as:1331]
at mx.charts::AxisRenderer/set gutters()[C:\work\flex\dmv_automation\projects\datavisualisation\src\mx\charts\ AxisRenderer.as:803]
at mx.charts.chartClasses::CartesianChart/updateAxisLayout()[C:\work\flex\dmv_auto mation\projects\datavisualisation\src\mx\charts\chartClasses\CartesianChart.as:2 032]
at mx.charts.chartClasses::CartesianChart/updateDisplayList()[C:\work\flex\dmv_aut omation\projects\datavisualisation\src\mx\charts\chartClasses\CartesianChart.as: 1359]
at mx.core::UIComponent/validateDisplayList()[C:\autobuild\3.3.0\frameworks\projec ts\framework\src\mx\core\UIComponent.as:6351]
at mx.managers::LayoutManager/validateDisplayList()[C:\autobuild\3.3.0\frameworks\ projects\framework\src\mx\managers\LayoutManager.as:622]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.3.0\framework s\projects\framework\src\mx\managers\LayoutManager.as:695]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.3.0\frameworks\proje cts\framework\src\mx\core\UIComponent.as:8633]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.3.0\frameworks\projec ts\framework\src\mx\core\UIComponent.as:8573]



Context from AxisRenderer:

(Note: the second branch of the if statement is executing, thus adjustment.bottom is false which leads to the code path with the bug.)



public function set gutters(value:Rectangle):void
{
var correctedGutters:Rectangle = value;

// This check will rarely succeed, because _gutters
// have been tweaked to represent placement.
if (_gutters &&
_gutters.left == correctedGutters.left &&
_gutters.right == correctedGutters.right &&
_gutters.top == correctedGutters.top &&
_gutters.bottom == correctedGutters.bottom)
{
_gutters = correctedGutters;
return;
}
else
{
adjustGutters(value,
{ left: false, top: false, right: false, bottom: false });
}
}





I am building the series list dynamically, it's a stacked column chart, and for me the bug occurs when there is one series and one data point.

I haven't been able to trigger the bug with the following example, which has a similar structure to my actual code.



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:local="*">




<mx:Script>
<![CDATA[
import mx.charts.series.ColumnSeries;
import mx.charts.chartClasses.Series;



[Bindable]
public var seriesList:Array = [];

public function buildSeriesList(seriesList:Array):Array {

var chartSeries:Array = new Array();

var index:int = 0;
for each (var series:Object in seriesList) {

var columnSeries:ColumnSeries = new ColumnSeries();
columnSeries.dataProvider = series.items;
columnSeries.dataFunction = myDataFunction;
columnSeries.displayName = series.category;
chartSeries.push( columnSeries );
}
return chartSeries;
}



private function categoryProvider(seriesList:Array):Array {
if (seriesList && seriesList.length > 0)
return (seriesList[0]).items;
return null;
}

private function myDataFunction(series:Series, item:Object, fieldName:String):Object {
if(fieldName == "yValue") {
return item.value;
}
else if(fieldName == "xValue") {
return item.category;
}
else
return null;
}



public function shortCategoryLabel(source:String):String {

return source;
}



public function longCategoryLabel(source:String):String {

return source;
}

private function onRefresh(event:Event):void {
this.seriesList = [ { category: "cat1" , items: [ { category: "Default Business Unit", value:574.1 }] }];
}

]]>
</mx:Script>



<mx:Button label="Refresh" click="onRefresh(event)" />

<mx:ColumnChart height="100%"
width="100%" type="stacked" series="{this.buildSeriesList(this.seriesList)}">

<mx:horizontalAxis>
<mx:CategoryAxis id="bottomAxis2" title="Horizontal Axis"
dataProvider="{this.categoryProvider(this.seriesList)}"
categoryField="category"
/>
</mx:horizontalAxis>

<mx:verticalAxis>
<mx:LinearAxis id="leftAxis2" title="Vertical Axis"/>
</mx:verticalAxis>



<mx:verticalAxisRenderers>
<mx:AxisRenderer
placement="left" styleName="verticalAxisRenderer"
axis="{leftAxis2}" verticalAxisTitleAlignment="vertical"
/>
</mx:verticalAxisRenderers>



<mx:horizontalAxisRenderers>
<mx:AxisRenderer
placement="bottom"
axis="{bottomAxis2}" verticalAxisTitleAlignment="flippedVertical"
>
</mx:AxisRenderer>
</mx:horizontalAxisRenderers>

</mx:ColumnChart>




</mx:Application>


解决方法:
In case someone still has this problem, here a quick fix.
Add an creationComplete event to your AxisRenderer:

<mx:AxisRenderer id="horizontalAR"
creationComplete="handleHAxisRendererCreationComplete(event)"
axis="{myHAxis}" />

<Script>
private function handleHAxisRendererCreationComplete(event:FlexEvent):void
{
var axisRenderer:AxisRenderer = event.target as AxisRenderer;
axisRenderer.setStyle('canStagger', (axisRenderer.numChildren == 1) ? false : true);
}
</Script>

原文地址:https://bugs.adobe.com/jira/browse/FLEXDMV-2275
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值