Пользовательский AxisRenderer

Я работаю с LineChart с CategoryAxis для горизонтальной оси, и мне нужно, чтобы каждая категория отображалась в очень индивидуальном формате. Использование CategoryAxis.LabelFunction недостаточно мощно для моих целей, так как оно позволяет только пользовательское форматирование текстового поля объекта Label. Специально для этого проекта мне нужно, чтобы каждая категория представляла собой сетку или HGroup из двух разных многострочных меток. Левая метка должна быть выровнена по левому краю, а правая — по правому краю.

Я попытался создать собственный класс, который extends Group и implements IDataRenderer. Однако public function set data(value:Object), определенный в IDataRenderer, кажется, всегда вызывается со значением как объект AxisLabel, который не передает внутри себя объект, а просто строку (AxisLabel.text)


В качестве альтернативы я попытался использовать LabelFunction для передачи закодированной строки, но даже это вызывает проблемы. Каким-то образом этот код не приводит к тому, что на CategoryAxis ничего не отображается:

public class HeatmapAxisLabelRenderer 
extends HGroup
implements IDataRenderer
{
public function HeatmapAxisLabelRenderer()
{
    super();

    this.includeInLayout = true;
    this.visible = true;

    this.width = 100;
    this.height = 40;
//      this.percentWidth = 100;
//      this.percentHeight = 100;
}


// Internal variable for the property value.
private var _data:Object;

// Make the data property bindable.
[Bindable("dataChange")]

// Define the getter method.
public function get data():Object {
    return _data;
}

// Define the setter method, and dispatch an event when the property
// changes to support data binding.
public function set data(value:Object):void {
    _data = value;

    if (value is AxisLabel && AxisLabel(value).text!=null) {
        var parts:Array = AxisLabel(value).text.split("|~|");
        if (parts.length != 2) return;

        var name:Label = new Label();
        name.text = parts[0];
        name.setStyle("textAlign","left");
        name.width = 100;

        var limit:Label = new Label();
        limit.text = parts[1];
        limit.setStyle("textAlign","right");
        limit.width = 100;

        this.addElement(name);
        this.addElement(limit);

        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    } else {
        trace("renderer bad value");
    }
}

person prismaticorb    schedule 29.05.2012    source источник


Ответы (1)


Проблема заключается в странном взаимодействии между Group и AxisRenderer, а также в том, что ваш рендерер (HGroup) имеет явные значения ширины/высоты (установленные в его конструкторе):

После установки data в вашем пользовательском рендерере AxisRenderer` сообщает пользовательскому рендереру, что его размер недействителен.

При этом Group правильно решает ничего не делать, потому что у него есть явная ширина/высота.

Я внес некоторые изменения, чтобы заставить это работать:

  • только установить ширину в конструкторе
  • не устанавливайте ширину дочерних меток (вы, вероятно, захотите поиграть с этим)
  • сделал переменные-члены объектов меток и создал их только один раз при создании дочерних элементов (сеттер для данных может вызываться часто)

Код:

package
{
    import mx.charts.AxisLabel;
    import mx.core.IDataRenderer;
    import mx.events.FlexEvent;

    import spark.components.HGroup;
    import spark.components.Label;

    public class HeatmapAxisLabelRenderer extends HGroup implements IDataRenderer
    {
        public function HeatmapAxisLabelRenderer()
        {
            super();
            this.width=100;
        }

        private var _data:Object;

        [Bindable("dataChange")]
        public function get data():Object {
                return _data;
        }

        private var nameLabel:Label;
        private var limit:Label;

        override protected function createChildren():void
        {
            super.createChildren();
            if (!nameLabel)
            {
                nameLabel=new Label();
                nameLabel.setStyle("textAlign","left");
                limit = new Label();
                limit.setStyle("textAlign", "right");
                addElement(nameLabel);
                addElement(limit);
            }
        }

        public function set data(value:Object):void
        {
            if (_data === value)
                return;

            _data = value;
            if (value is AxisLabel && AxisLabel(value).text!=null)
            {
                var parts:Array = AxisLabel(value).text.split("|~|");
                if (parts.length == 2)
                {
                    nameLabel.text = parts[0];
                    limit.text = parts[1];
                }
            }
            else
            {
                trace("renderer bad value");
            }
            dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
        }
    }
}
person Sunil D.    schedule 30.05.2012