В следующем примере мы рассмотрим диаграмму, которая получает данные из контейнера и обновляет их автоматически. Когда в контейнер добавляются новые данные, диаграмма не обновляется полностью: новые точки добавляются в график на лету каждые 2 секунды. Этот принцип удобно использовать при создании динамически обновляемых виджетов.
Пример основан на тестовом приложении Sales, к которому мы добавим диаграмму для отображения динамики новых заказов, то есть создания новых экземпляров сущности Order
.
-
Скачайте приложение Sales и добавьте к нему компонент charts, следуя инструкции из раздела [chart_project_setup].
-
Создайте в Studio новый пустой экран. Назовите его orders-history, так как в нём будет отображаться история создания новых заказов.
-
Добавьте к экрану компонент
serialChart
. Чтобы реализовать инкрементальное обновление данных, необходимо создать контейнер данных с типомCollectionContainer
и привязать к нему диаграмму. В этом примере мы не будем загружать данные из базы, вместо этого мы будем создавать тестовые данные на лету, поэтому загрузчик данных в контейнере создавать не нужно.Для оси категорий укажите атрибут
date
, для оси значений – атрибутamount
.link:../../../../source/chart/chart_incremental-update.xml[role=include]
-
Для обновления данных на лету используйте {main_man_url}/gui_Timer.html[timer] – специальный UI-компонент, который будет отправлять HTTP-запросы на сторону сервера.
-
Переключитесь на вкладку Designer.
-
В группе Non-visual components в палитре компонентов найдите Timer и перетащите его в область иерархии компонентов экрана.
-
Выделите компонент в иерархии и перейдите на вкладку Properties.
-
Задайте идентификатор таймера в поле id.
-
Допустим, мы хотим, чтобы данные обновлялись каждые 2 секунды, в этом случае в поле delay укажите значение 2000 миллисекунд.
-
В поле onTimer укажите имя метода Java –
updateChart
. Этот метод будет вызываться каждый раз при срабатывании события таймера. Сгенерируйте метод в контроллере экрана, нажав на кнопку >>. -
Поставьте флажки repeating и autostart.
-
-
Откройте контроллер экрана
OrdersHistory
. Для разработки логики работы таймера инжектируйте следующие зависимости:timeSource
,metadata
и контейнер данных для сущностиOrder
. Мы будем генерировать новый экземпляр сущностиOrder
с произвольным значениемamount
при каждом событии срабатывания таймера. Новый экземпляр добавляется к контейнеру данных с помощью методаgetMutableItems().add()
.Инициализируйте диаграмму в методе
onInit()
, создав таким же образом исходный экземпляр сущностиOrder
.link:../../../../source/chart/chart_incremental-update.java[role=include]
На этом этапе диаграмма полностью функциональна, но размер контейнера данных после запуска таймера будет стремительно расти, поэтому реализуем ограничение количества отображаемых заказов.
-
Создайте экземпляр класса
Queue
для очереди заказов. При каждом срабатывании таймера созданный заказ будет добавлен наверх очередиitemsQueue
. Когда размер очереди превышает 10 заказов, самый старый заказ удаляется.private Queue<Order> itemsQueue = new LinkedList<>();
link:../../../../source/chart/chart_incremental-update_2.java[role=include]
- Результат
-
Данные поступают в браузер инкрементально. Если открыть консоль разработчика в Chrome, на вкладке Network будет видно, что каждые 2 секунды страница отправляет HTTP-запрос на backend и в ответе получает очень маленький JSON, содержащий только операции
add
иremove
со значениями поляamount
. Это позволяет избежать повторной пересылки всех данных диаграммы.