Часть 6: Содержание
- Создание статистической диаграммы для показа распределения дней рождений по месяцам.
Статистика дней рождений
Каждый адресат в нашем приложении AddressApp имеет свой день рождения. Было бы неплохо видеть некоторую статистику о том, когда они празднуют свои дни рождения.
Мы будем использовать столбцовую диаграмму, один столбец будет символизировать один месяц. Каждый столбец будет показывать, сколько дней рождений приходится на его месяц.
FXML-представление статистики
-
Начните с создания внутри пакета
ch.makery.address.view
файлаBirthdayStatistics.fxml
(правый клик на пакете | New | other… | New FXML Document).
-
Откройте файл
BirthdayStatistics.fxml
в приложении Scene Builder. -
Выберите корневой компонент
AnchorPane
. Во вкладке Layout установите значение Pref Width в 620, а Pref Height в 450. -
Добавьте на панель
AnchorPane
компонентBarChart
. -
Кликните правой кнопкой мышки на добавленном
BarChart
и выберите Fit to Parent. -
Сохраните fxml-файл, перейдите в Eclipse и обновите проект.
Перед тем, как вернутся в приложение Scene Builder, давайте создадим контроллер и в классе MainApp
свяжем всё между собой.
Класс-контроллер статистики
В пакете ch.makery.address.view
создайте класс BirthdayStatisticsController.java
.
Перед тем, как я начну объяснять что к чему, взгляните на содержимое этого класса:
BirthdayStatisticsController.java
package ch.makery.address.view; import java.text.DateFormatSymbols; import java.util.Arrays; import java.util.List; import java.util.Locale; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.chart.BarChart; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.XYChart; import ch.makery.address.model.Person; /** * Контроллер для представления статистики дней рождений. * * @author Marco Jakob */ public class BirthdayStatisticsController { @FXML private BarChart<String, Integer> barChart; @FXML private CategoryAxis xAxis; private ObservableList<String> monthNames = FXCollections.observableArrayList(); /** * Инициализирует класс-контроллер. Этот метод вызывается автоматически * после того, как fxml-файл был загружен. */ @FXML private void initialize() { // Получаем массив с английскими именами месяцев. String[] months = DateFormatSymbols.getInstance(Locale.ENGLISH).getMonths(); // Преобразуем его в список и добавляем в наш ObservableList месяцев. monthNames.addAll(Arrays.asList(months)); // Назначаем имена месяцев категориями для горизонтальной оси. xAxis.setCategories(monthNames); } /** * Задаёт адресатов, о которых будет показана статистика. * * @param persons */ public void setPersonData(List<Person> persons) { // Считаем адресатов, имеющих дни рождения в указанном месяце. int[] monthCounter = new int[12]; for (Person p : persons) { int month = p.getBirthday().getMonthValue() - 1; monthCounter[month]++; } XYChart.Series<String, Integer> series = new XYChart.Series<>(); // Создаём объект XYChart.Data для каждого месяца. // Добавляем его в серии. for (int i = 0; i < monthCounter.length; i++) { series.getData().add(new XYChart.Data<>(monthNames.get(i), monthCounter[i])); } barChart.getData().add(series); } }
Как работает этот контроллер
-
Контроллеру нужен доступ к двум элементам из нашего fxml-файла:
barChart
использует типы данныхString
иInteger
. Тип данныхString
отображает название месяцев на оси X, а тип данныхInteger
- количество записей в конкретном месяце.- Ось
xAxis
мы используем для добавления названий месяцев.
-
Метод
initialize()
заполняет ось X строковыми значениями названий всех месяцев. -
Метод
setPersonData(...)
будет доступен классуMainApp
для передачи данных об адресатах. Он проходится по всем адресатам и подсчитывает количество дней рождений в каждом месяце. Потом он добавляетXYChart.Data
для каждого месяца в серию данныхXYChart.Series
. Каждый объектXYChart.Data
будет представлять один столбец диаграммы.
Соединяем представление и контроллер
-
В приложении Scene Builder откройте файл
BirthdayStatistics.fxml
. -
Во вкладке Controller установите в качестве контроллера
BirthdayStatisticsController
. -
Выберите компонент
BarChart
и в свойстве fx:id установите значениеbarChart
. -
Выберите
CategoryAxis
и в свойстве fx:id установите значениеxAxis
. -
Для будущей стилизации, во вкладке Properties вы можете добавить название своей диаграммы.
Соединяем представление/контроллер с классом MainApp
Для отображения статистики дней рождений мы будем использовать тот же механизм, что ранее использовали для отображения окна редактирования данных об адресатах.
Добавьте следующий метод в класс MainApp
:
/** * Открывает диалоговое окно для вывода статистики дней рождений. */ public void showBirthdayStatistics() { try { // Загружает fxml-файл и создаёт новую сцену для всплывающего окна. FXMLLoader loader = new FXMLLoader(); loader.setLocation(MainApp.class.getResource("view/BirthdayStatistics.fxml")); AnchorPane page = (AnchorPane) loader.load(); Stage dialogStage = new Stage(); dialogStage.setTitle("Birthday Statistics"); dialogStage.initModality(Modality.WINDOW_MODAL); dialogStage.initOwner(primaryStage); Scene scene = new Scene(page); dialogStage.setScene(scene); // Передаёт адресатов в контроллер. BirthdayStatisticsController controller = loader.getController(); controller.setPersonData(personData); dialogStage.show(); } catch (IOException e) { e.printStackTrace(); } }
Всё готово. Правда, пока метод showBirthdayStatistics()
нигде не вызывается. К счастью, в разметке RootLayout.fxml
у нас есть меню, которое может быть использовано для этих целей.
Отображаем меню статистики
В класс RootLayoutController
добавьте метод, который будет обрабатывать нажатие пункта меню Show Birthday Statistics:
/** * Открывает статистику дней рождений. */ @FXML private void handleShowBirthdayStatistics() { mainApp.showBirthdayStatistics(); }
Теперь в приложении Scene Builder откройте файл RootLayout.fxml
и создайте меню Statistics с единственным пунктом меню Show Statistics:
Выберите пункт меню Show Statistics и в качестве значения свойства On Action
установите метод handleShowBirthdayStatistics
.
Перейдите в среду разработки Eclipse, обновите проект и протестируйте ваше приложение.
Больше информации о диаграммах в JavaFX
Хороший источник для получения дополнительной информации о диаграммах в JavaFX - официальный учебник от Oracle Работа с диаграммами в JavaFX
Что дальше?
В последней, 7-й части учебника мы наконец развернём наше приложение (то есть, упакуем и доставим приложение нашим пользователям).