数据绑定

使用 DataProvider 接口

DataProvider 接口有两个标准实现:ListDataProviderContainerDataProvider 类。

一个 DataProvider 的实例会被传入图表配置的 setDataProvider() 方法。这种提供图表数据的方法是最通用的,但需要在界面控制器中创建 DataProviderDataItem 的实例。

DataProvider 实例中包含用于展示的实体属性或值,需要在图表属性中定义。根据图表类型的不同,图表属性也不一样。例如,对于 chart:pieChart 组件,需要定义 valueFieldtitleField 属性。属性值可以使用这些类型:IntegerLongDoubleStringBooleanDate

ListDataProvider

ListDataProvider 包含了一个 DataItem 实例的列表,图表的数据将从这个列表里获取。DataItem 接口有一些标准的实现:

  • EntityDataItem 包含任意实体类的实例,从该实例中获取图表数据。

    @Autowired
    private PieChart chart;
    @Autowired
    private Metadata metadata;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        ListDataProvider dataProvider = new ListDataProvider();
        dataProvider.addItem(new EntityDataItem(
                (Entity) valueDescription(75, "Sky")));
        dataProvider.addItem(new EntityDataItem(
                (Entity) valueDescription(7, "Shady side of pyramid")));
        dataProvider.addItem(new EntityDataItem(
                (Entity) valueDescription(18, "Sunny side of pyramid")));
    
        chart.setDataProvider(dataProvider);
    }
    
    private ValueDescription valueDescription(Integer value, String description) {
        ValueDescription entity = metadata.create(ValueDescription.class);
        entity.setValue(value);
        entity.setDescription(description);
        return entity;
    }
  • MapDataItemScreen 键值对集合,从中获取图表数据。

    @Autowired
    private PieChart chart;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        ListDataProvider dataProvider = new ListDataProvider();
        dataProvider.addItem(new MapDataItem(
                ImmutableMap.of("value", 75, "description", "Sky")));
        dataProvider.addItem(new MapDataItem(
                ImmutableMap.of("value", 7, "description", "Shady side of pyramid")));
        dataProvider.addItem(new MapDataItem(
                ImmutableMap.of("value", 18, "description", "Sunny side of pyramid")));
    
        chart.setDataProvider(dataProvider);
  • SimpleDataItem 使用任意 public 类的实例,从中获取图表数据。

    @Autowired
    private PieChart chart;
    
    @Subscribe
    protected void onInit(InitEvent event) {
        ListDataProvider dataProvider = new ListDataProvider();
        dataProvider.addItem(new SimpleDataItem(
                new ValueDescription(75, "Sky")));
        dataProvider.addItem(new SimpleDataItem(
                new ValueDescription(7, "Shady side of pyramid")));
        dataProvider.addItem(new SimpleDataItem(
                new ValueDescription(18, "Sunny side of pyramid")));
    
        chart.setDataProvider(dataProvider);
    }
    
    public class ValueDescription {
        private Integer value;
        private String description;
    
        public ValueDescription(Integer value, String description) {
            this.value = value;
            this.description = description;
        }
    
        public Integer getValue() {
            return value;
        }
    
        public String getDescription() {
            return description;
        }
    }

ContainerDataProvider

ContainerDataProvider 用于给 Chart 组件分配一个 CollectionContainer

假设我们有数据容器和数据加载器用来加载 TransportCount 实例。下面是界面 XML 描述的部分内容:

<data>
    <collection id="transportCountsDc" class="charts.ex1.entity.TransportCount">
        <fetchPlan extends="_base"/>
        <loader id="transportCountsDl">
            <query>
                <![CDATA[select e from sample_TransportCount e order by e.year]]>
            </query>
        </loader>
    </collection>
</data>
<facets>
    <dataLoadCoordinator auto="true"/>
</facets>
<layout>
    <chart:serialChart id="stackedArea"
                       categoryField="year"
                       dataContainer="transportCountsDc"
                       height="100%"
                       marginLeft="0"
                       marginTop="10"
                       plotAreaBorderAlpha="0"
                       width="100%">
        <!-- ... -->
    </chart:serialChart>
</layout>

界面控制器定义了 onInit() 方法,设置了 stackedArea 图表的数据提供者。数据提供者基于 transportCountsDc 数据容器创建。

@Autowired
private CollectionContainer<TransportCount> transportCountsDc;

@Autowired
private SerialChart stackedArea;

@Subscribe
private void onInit(InitEvent event) {
    stackedArea.setDataProvider(new ContainerDataProvider(transportCountsDc));
    stackedArea.setCategoryField("year");
}

这种方式需要一个实体来表示图表数据。如果应用程序数据模型中已经存在这样的一个实体,并且图表数据是要显示为表格时,这种方式可能就比较方便。

使用简易数据绑定

这种方法适合快速完成图表的原型,数据没有绑定至任何数据容器。使用 chart:data 和内部的 item 元素可以直接在图表的 XML 描述中设置键值对类型的数据,示例:

<chart:pieChart id="pieChart"
                titleField="key"
                valueField="value">
    <chart:data>
        <chart:item>
            <chart:property name="key" value="piece of apple pie"/>
            <chart:property name="value" value="70" type="int"/>
        </chart:item>
        <chart:item>
            <chart:property name="key" value="piece of blueberry pie"/>
            <chart:property name="value" value="20" type="int"/>
        </chart:item>
        <chart:item>
            <chart:property name="key" value="piece of cherry pie"/>
            <chart:property name="value" value="10" type="int"/>
        </chart:item>
    </chart:data>
</chart:pieChart>

另外,也可以在界面控制器使用数据绑定 API 设置键值对。

将图表组件添加至界面,然后使用 addData() 方法填充数据,将一组使用键值对的 MapDataItem 实例作为参数传入:

<chart:pieChart id="pieChart"
                titleField="key"
                valueField="value"/>
@Autowired
private PieChart pieChart;

@Subscribe
private void onBeforeShow(BeforeShowEvent event) {
    pieChart.addData(MapDataItem.of("key", "piece of apple pie",
            "value", 70),
            MapDataItem.of("key", "piece of blueberry pie",
                    "value", 20),
            MapDataItem.of("key", "piece of cherry pie",
                    "value", 10));
}
simple pie chart
简单饼图