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