第6部分的主题
- 创建一个统计图显示生日的分布。
生日统计
在AddressApp中所有人员都有生日。当我们人员庆祝他们生日的时候,如果有一些生日的统计不是会更好。
我们使用柱状图,包含每个月的一个条形。每个条形显示在指定月份中有多少人需要过生日。
统计FXML视图
在
ch.makery.address.view
包中我们开始创建一个BirthdayStatistics.fxml
(*右击包|New|other..|New FXML Document*)在Scene Builder中打开
BirthdayStatistics.fxml
文件。选择根节点
AnchorPane
。在*Layout*组中设置*Pref Width*为620,*Pref Height*为450。添加
BarChart
到AnchorPane
中。右击
BarChart
并且选择*Fit to Parent*。保存fxml文件,进入到Eclipse中,F5刷新项目。
在我们返回到Scene Builder之前,我们首先创建控制器,并且在我们的MainApp
中准备好一切。
统计控制器
在view包 ch.makery.address.view
中创建一个Java类,称为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; /** * The controller for the birthday statistics view. * * @author Marco Jakob */ public class BirthdayStatisticsController { @FXML private BarChart<String, Integer> barChart; @FXML private CategoryAxis xAxis; private ObservableList<String> monthNames = FXCollections.observableArrayList(); /** * Initializes the controller class. This method is automatically called * after the fxml file has been loaded. */ @FXML private void initialize() { // Get an array with the English month names. String[] months = DateFormatSymbols.getInstance(Locale.ENGLISH).getMonths(); // Convert it to a list and add it to our ObservableList of months. monthNames.addAll(Arrays.asList(months)); // Assign the month names as categories for the horizontal axis. xAxis.setCategories(monthNames); } /** * Sets the persons to show the statistics for. * * @param persons */ public void setPersonData(List<Person> persons) { // Count the number of people having their birthday in a specific month. 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<>(); // Create a XYChart.Data object for each month. Add it to the series. for (int i = 0; i < monthCounter.length; i++) { series.getData().add(new XYChart.Data<>(monthNames.get(i), monthCounter[i])); } barChart.getData().add(series); } }
控制器如何工作
控制器需要从FXML文件中访问两个元素:
barChar
:它有String
和Integer
类型。String
用于x轴上的月份,Integer
用于指定月份中人员的数量。xAxis
:我们使用它添加月字符串
initialize()
方法使用所有月的列表填充x-axis
。setPersonData(…)
方法将由MainApp
访问,设置人员数据。它遍历所有人员,统计出每个月生日的人数。然后它为每个月添加XYChart.Data
到数据序列中。每个XYChart.Data
对象在图表中表示一个条形。
连接视图和控制器
在Scene Builder中打开
BirthdayStatistics.fxml
。在Controller组中设置
BirthdayStatisticsController
为控制器。选择
BarChart
,并且选择barChar
作为fx:id属性(在*Code*组中)选择
CategoryAxis
,并且选择xAxis
作为fx:id属性。
你可以添加一个标题给
BarChar
(在*Properties*组中)进一步修饰。
连接View/Controller和MainApp
我们为*生日统计*使用与*编辑人员对话框*相同的机制,一个简单的弹出对话框。
添加下面的方法到MainApp
类中
/** * Opens a dialog to show birthday statistics. */ public void showBirthdayStatistics() { try { // Load the fxml file and create a new stage for the popup. 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); // Set the persons into the controller. BirthdayStatisticsController controller = loader.getController(); controller.setPersonData(personData); dialogStage.show(); } catch (IOException e) { e.printStackTrace(); } }
一切设置完毕,但是我们没有任何东西实际上调用新的showBirthdayStatistics()
方法。幸运的是我们已经在RootLayout.fxml
中有一个菜单,它可以用于这个目的。
显示生日统计菜单
在RootLayoutController
中添加下面的方法,它将处理*显示生日统计*菜单项的用户点击。
/** * Opens the birthday statistics. */ @FXML private void handleShowBirthdayStatistics() { mainApp.showBirthdayStatistics(); }
现在,使用Scene Builder打开RootLayout.fxml
文件。创建Staticstic 菜单
,带有一个Show Statistcs MenuItem
:
选择Show Statistics MenuItem
,并且选择handleShowBirthdayStatistics
作为On Action
(在*Code*组中)。
进入到Eclipse,刷新项目,测试它。
JavaFX Chart的更多信息
更多信息的一个好地方是官方Oracle教程,使用JavaFX Chart.
下一步做什么?
在最后的教程第7部分 中,我们将最后部署我们的应用(例如:打包并且发布应用到我们的用户)