Откройте в CUBA Studio вкладку Screens и создайте экран в модуле web. Введите значение com/sample/library/web/charts/statistics.xml
в поле Reference. В полях Id, Controller Name и Messages Pack будут сгенерированы подходящие значения. Сохраните изменения. Далее перейдите на вкладку XML и замените ее содержимое на следующий код:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/window.xsd" caption="msg://statistic" class="com.sample.library.web.charts.statistics.Statistics" messagesPack="com.sample.library.web.charts.statistics" xmlns:chart="http://schemas.haulmont.com/charts/charts.xsd"> <dsContext> <collectionDatasource id="pieDs" class="com.sample.library.entity.BooksByGenre" refreshMode="NEVER" view="_local"/> </dsContext> <layout spacing="true"> <tabSheet height="100%" width="100%"> <tab id="pieChartTab" caption="msg://booksByGenres"> <hbox expand="pieChart" height="100%" margin="true" spacing="true" width="100%"> <chart:pieChart id="pieChart" angle="30" balloonText="[[genre]] - [[percents]]%" datasource="pieDs" depth3D="15" height="100%" titleField="genre" valueField="countOfBooks" width="100%"> <chart:exportConfig menuTop="0px"> <chart:menuItems> <chart:menu format="PNG" icon="VAADIN/resources/amcharts/images/export.png"/> </chart:menuItems> </chart:exportConfig> </chart:pieChart> <table columnControlVisible="false" height="100%" width="300px"> <columns> <column id="genre"/> <column id="countOfBooks"/> </columns> <rows datasource="pieDs"/> </table> </hbox> </tab> <tab id="stackedChartTab" caption="msg://countOfBooksByPublisherAndYear" spacing="true"> <chart:serialChart id="stackedChart" categoryField="year" height="100%" plotAreaFillAlphas="0.1" width="100%"> <chart:chartCursor/> <chart:legend markerType="TRIANGLE_RIGHT" position="TOP" valueAlign="LEFT"/> <chart:categoryAxis startOnAxis="true" title="msg://year"/> <chart:valueAxes> <chart:axis gridAlpha="0.07" position="LEFT" stackType="REGULAR" title="msg://countOfBooks"/> </chart:valueAxes> <chart:exportConfig menuTop="0px"> <chart:menuItems> <chart:menu format="PNG" icon="VAADIN/resources/amcharts/images/export.png"/> </chart:menuItems> </chart:exportConfig> </chart:serialChart> </tab> </tabSheet> </layout> </window>
В корневой элемент дескриптора экрана добавлен атрибут xmlns:chart
:
<window xmlns:chart="http://schemas.haulmont.com/charts/charts.xsd" ... >
Созданный нами экран содержит панель с двумя вкладками. На первой находится круговая диаграмма, представляющая распределение книг по жанрам:
<chart:pieChart id="pieChart" angle="30" balloonText="[[genre]] - [[percents]]%" datasource="pieDs" depth3D="15" height="100%" titleField="genre" valueField="countOfBooks" width="100%"> <chart:exportConfig menuTop="0px"> <chart:menuItems> <chart:menu format="PNG" icon="VAADIN/resources/amcharts/images/export.png"/> </chart:menuItems> </chart:exportConfig> </chart:pieChart>
Даграмма получает данные из источника pieDs
, указанного в атрибуте datasource
. Для отображения названий и значений используются атрибуты genre
и countOfBooks
сущности BooksByGenre
, список экземпляров которой находится в источнике данных. С источником данных соединена также таблица, поэтому она отображает
те же данные, что и диаграмма.
Компонент pieChart
содержит следующие атрибуты:
-
angle
- определяет угол наклона диаграммы. Может принимать значения от0
до90
. -
balloonText
- определяет текст всплывающей подсказки при наведении на отделяемую часть диаграммы. Доступны для использования тэги[[value]]
,[[title]]
,[[persents]]
,[[description]]
, а также ключи изDataItem
, список которых хранится в экземпляреDataProvider
, либо имена атрибутов сущности в источнике данных. -
depth3D
- толщина диграммы. При использовании совместно с атрибутомangle
позволяет создать эффект объема. -
titleField
- ключ из набора пар, содержащихся в объектахDataItem
, список которых хранится в экземпляреDataProvider
, по которому будет взято значение для заголовка сектора в круговой диаграмме. -
valueField
- ключ из набора пар, содержащихся в объектахDataItem
, список которых хранится в экземпляреDataProvider
, по которому будет взято значение для сектора.
Компонент pieChart
содержит следующие элементы:
-
chart:legend
- определяет легенду графика. Атрибутposition
определяет положение легенды относительно диаграммы,markerType
- форму маркера, помечающего информацию о каждом секторе диаграммы. -
chart:exportConfig
- добавляет возможность сохранить полученный график. АтрибутыmenuTop
,menuLeft
,menuRight
,menuBottom
позволяют задать положение кнопки сохранения. В примере кнопка располагается в правом верхнем углу диаграммы.Элемент
chart:menuItems
содержит настройки сохранения. Кроме используемого в примере форматаpng
поддерживается сохранение в форматахjpg
,svg
иpdf
. Атрибутicon
содержит путь к изображению, которое будет использоваться в качестве кнопки импорта.
Вторая вкладка содержит график, отражающий количество книг, выпущенных в разные годы несколькими издательствами:
<chart:serialChart id="stackedChart" categoryField="year" height="100%" width="100%"> <chart:chartCursor/> <chart:legend markerType="TRIANGLE_RIGHT" position="TOP" valueAlign="LEFT"/> <chart:categoryAxis startOnAxis="true" title="msg://year"/> <chart:valueAxes> <chart:axis position="LEFT" stackType="REGULAR" title="msg://countOfBooks"/> </chart:valueAxes> <chart:exportConfig menuTop="0px"> <chart:menuItems> <chart:menu format="PNG" icon="VAADIN/resources/amcharts/images/export.png"/> </chart:menuItems> </chart:exportConfig> </chart:serialChart>
Эта диаграмма получает данные через DataProvider
, созданный в контроллере (см. ниже), поэтому атрибут datasource
не указан.
Атрибуты chart:serialChart
:
-
categoryField
- ключ из набора пар, содержащихся в объектахDataItem
, список которых хранится в экземпляреDataProvider
, по которому будут взяты значения для подписи оси категорий.
Элементы chart:serialChart
:
-
chart:chartCursor
- необязательный элемент, добавляющий на график курсор, который следует за движениями мыши и отображает всплывающую подсказку со значением графика, соответствующим точке нахождения курсора. -
chart:categoryAxis
- элемент, описывающий ось категорий. Установка атрибутуstartOnAxis
значенияtrue
дает указание начинать отрисовывать график сразу от оси значений. По умолчанию этот атрибут имеет значениеfalse
. В этом случае между осью значений и графиком имеется некоторый помежуток. Атрибутtitle
задает заголовок оси категорий. -
chart:valueAxes
- элемент, описывающий вертикальные оси значений. В данном случае используется только одна ось, описываемая элементомchart:axis
. Атрибутposition
задает положение оси значений относительно диаграммы. Установка атрибутуstackType
значенияREGULAR
говорит о том, что используется диаграмма с накоплением. По умолчанию значение этого атрибута -none
, в таком случае используется диаграмма без накопления.
Перейдите на вкладку Controller и замените ее содержимое на следующий код:
package com.sample.library.web.charts.statistics; import com.haulmont.charts.gui.amcharts.model.Graph; import com.haulmont.charts.gui.amcharts.model.GraphType; import com.haulmont.charts.gui.amcharts.model.charts.SerialChart; import com.haulmont.charts.gui.amcharts.model.data.ListDataProvider; import com.haulmont.charts.gui.amcharts.model.data.MapDataItem; import com.haulmont.charts.gui.components.charts.Chart; import com.haulmont.cuba.gui.components.AbstractWindow; import com.haulmont.cuba.gui.data.CollectionDatasource; import com.sample.library.entity.BooksByGenre; import com.sample.library.service.StatisticsService; import javax.inject.Inject; import java.util.List; import java.util.Map; import java.util.UUID; public class Statistics extends AbstractWindow { @Inject private CollectionDatasource<BooksByGenre, UUID> pieDs; @Inject private Chart stackedChart; @Inject private StatisticsService statisticsService; public void init(Map<String, Object> param) { initPieChart(); initStackedChart(); } private void initPieChart() { pieDs.refresh(); List<BooksByGenre> booksByGenreList = statisticsService.getCountOfBooksByGenre(); for (BooksByGenre booksByGenre : booksByGenreList) { pieDs.includeItem(booksByGenre); } } private void initStackedChart() { List<String> allPublishers = statisticsService.getTopPublishers(5); Map<Integer, Map<String, Long>> structuredData = statisticsService.getCountOfBooksByPublisherAndYear(); ListDataProvider dataProvider = new ListDataProvider(); for (Map.Entry<Integer, Map<String, Long>> entry : structuredData.entrySet()) { MapDataItem mapDataItem = new MapDataItem().add("year", entry.getKey()); for (String publisher : allPublishers) { if (entry.getValue().containsKey(publisher)) { mapDataItem.add(publisher, entry.getValue().get(publisher)); } else { mapDataItem.add(publisher, 0); } } dataProvider.addItem(mapDataItem); } SerialChart stackedChartConfiguration = (SerialChart) stackedChart.getConfiguration(); stackedChartConfiguration.setDataProvider(dataProvider); Graph[] graphs = new Graph[allPublishers.size()]; int i = 0; for (String publisher : allPublishers) { Graph publisherGraph = new Graph(); publisherGraph.setFillAlphas(0.6); publisherGraph.setLineAlpha(0.4); publisherGraph.setTitle(publisher); publisherGraph.setType(GraphType.LINE); publisherGraph.setValueField(publisher); publisherGraph.setBalloonText(publisher + " - [[year]] year: [[" + publisher + "]] books"); graphs[i] = publisherGraph; i++; } stackedChartConfiguration.addGraphs(graphs); } }
В методе initPieChart()
происходит заполнение источника данных pieDs
данными, полученными из сервиса. Метод refresh()
производит инициализацию источника данных. Этот метод необходимо вызвать, несмотря на атрибут refreshMode="NEVER"
, установленный в XML-дескрипторе.
В методе initStackedChart(List<String> allPublishers)
происходит установка данных в диаграмму с накоплением. Диаграммы подобного типа показывают отношение отдельных составляющих
к их совокупному значению. В метод передается список издателей, выпустивших наибольшее количество экземпляров книг, находящихся
в библиотеке. Для каждого издателя строится график, представляющий количество книг, выпущенных в разные годы. Графику соответствует
экземпляр класса Graph
. Рассмотрим методы настройки графиков:
-
setFillAlphas(0.6)
- устанавливает степень непрозрачности заливки. -
setLineAlpha(0.4)
- устанавливает толщину линии графика. Допустимые значения от0
до1
. -
setTitle(publisher)
- устанавливает заголовок графика. -
setType(GraphType.LINE)
- устанавливает тип отбражения данных. -
setValueField(publisher)
- ключ из набора пар, содержащихся в объектахDataItem
, список которых хранится в экземпляреDataProvider
, по которому будет взято значение для графика. -
setBaloonText(publisher + " - [[year]] year: [[" + publisher + "]] books")
- устанавливает значение всплывающей подсказки.
Посмотрим, как созданный нами экран выглядит в работающем приложении. Добавьте созданный экран в меню, затем пересоберите проект командой
-> и зайдите в систему. Откройте экран со статистикой.На диаграмме с накоплением проиллюстрирована работа курсора, который выводит подробную информацию о количестве книг, выпущенных издателями в выбранном году.