`
Fonkie
  • 浏览: 67240 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

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
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics