Пользовательский 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");
    }
}

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));
        }
    }
}
Другие вопросы по тегам