本节概要
本节将使用报告界面显示每日、每周、每月、每季度和每年的支出、收入和余额情况。
创建界面
首先要创建界面,在view包下创建reportFrame.fxml文件,使用Scene Builder设计界面,其各个控件的属性和事件方法参考下面的代码:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="AccountSystem.controller.ReportFrameController">
<children>
<TabPane prefHeight="400.0" prefWidth="600.0" rotateGraphic="true" tabClosingPolicy="UNAVAILABLE"
tabMaxHeight="200.0" tabMaxWidth="500.0">
<tabs>
<Tab text="日报告">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<BorderPane prefHeight="361.0" prefWidth="600.0">
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"
BorderPane.alignment="CENTER">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label fx:id="thisDayBalanceLabel" text="余额"/>
<Label fx:id="thisDayBalanceShowLabel" prefWidth="150.0"
textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</children>
</HBox>
</bottom>
<center>
<PieChart fx:id="thisDayPieChart" BorderPane.alignment="CENTER"/>
</center>
<left>
<VBox alignment="CENTER" prefHeight="229.0" prefWidth="136.0" spacing="10.0"
BorderPane.alignment="CENTER">
<children>
<Label fx:id="thisDayOutputLabel" text="本日支出"/>
<Label fx:id="thisDayOutputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
<Label fx:id="thisDayInputLabel" text="本日收入"/>
<Label fx:id="thisDayInputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</left>
<top>
<VBox alignment="CENTER" prefHeight="50.0" prefWidth="600.0"
BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="thisDayComboBox" onAction="#thisDayComboBoxEvent"
prefWidth="150.0"/>
</children>
</VBox>
</top>
</BorderPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="周报告">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<BorderPane prefHeight="361.0" prefWidth="600.0">
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"
BorderPane.alignment="CENTER">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label fx:id="thisWeekBalanceLabel" text="余额"/>
<Label fx:id="thisWeekShowBalanceLabel" prefWidth="150.0"
textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</children>
</HBox>
</bottom>
<center>
<PieChart fx:id="thisWeekPieChart" BorderPane.alignment="CENTER"/>
</center>
<left>
<VBox alignment="CENTER" prefHeight="229.0" prefWidth="136.0" spacing="10.0"
BorderPane.alignment="CENTER">
<children>
<Label fx:id="thisWeekOutputLabel" text="本周支出"/>
<Label fx:id="thisWeekOutputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
<Label fx:id="thisWeekInputLabel" text="本周收入"/>
<Label fx:id="thisWeekInputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</left>
<top>
<VBox alignment="CENTER" prefHeight="50.0" prefWidth="600.0"
BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="thisWeekComboBox" onAction="#thisWeekComboBoxEvent"
prefWidth="150.0"/>
</children>
</VBox>
</top>
</BorderPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="月报告">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<BorderPane prefHeight="361.0" prefWidth="600.0">
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"
BorderPane.alignment="CENTER">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label fx:id="thisMonthBalanceLabel" text="余额"/>
<Label fx:id="thisMonthBalanceShowLabel" prefWidth="150.0"
textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</children>
</HBox>
</bottom>
<center>
<PieChart fx:id="thisMonthPieChart" BorderPane.alignment="CENTER"/>
</center>
<left>
<VBox alignment="CENTER" prefHeight="261.0" prefWidth="136.0" spacing="20.0"
BorderPane.alignment="CENTER">
<children>
<Label fx:id="thisMonthOutputLabel" text="本月支出"/>
<Label fx:id="thisMonthOutputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
<Label fx:id="thisMonthInputLabel" text="本月收入"/>
<Label fx:id="thisMonthInputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</left>
<top>
<VBox alignment="CENTER" prefHeight="50.0" prefWidth="100.0"
BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="thisMonthComboBox" onAction="#thisMonthComboBoxEvent"
prefWidth="150.0"/>
</children>
</VBox>
</top>
</BorderPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="季度报告">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<BorderPane prefHeight="361.0" prefWidth="600.0">
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"
BorderPane.alignment="CENTER">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label fx:id="thisSeasonBalanceLabel" text="余额"/>
<Label fx:id="thisSeasonBalanceShowLabel" prefWidth="150.0"
textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</children>
</HBox>
</bottom>
<center>
<PieChart fx:id="thisSeasonPieChart" BorderPane.alignment="CENTER"/>
</center>
<left>
<VBox alignment="CENTER" prefHeight="261.0" prefWidth="136.0" spacing="20.0"
BorderPane.alignment="CENTER">
<children>
<Label fx:id="thisSeasonOutputLabel" text="本季度支出"/>
<Label fx:id="thisSeasonOutputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
<Label fx:id="thisSeasonInputLabel" text="本季度收入"/>
<Label fx:id="thisSeasonInputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</left>
<top>
<VBox alignment="CENTER" prefHeight="50.0" prefWidth="100.0"
BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="thisSeasonComboBox" onAction="#thisSeasonComboBoxEvent"
prefWidth="150.0"/>
</children>
</VBox>
</top>
</BorderPane>
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="年报告">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<BorderPane prefHeight="361.0" prefWidth="600.0">
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"
BorderPane.alignment="CENTER">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
<children>
<Label fx:id="thisYearBalanceLabel" text="余额"/>
<Label fx:id="thisYearBalanceShowLabel" prefWidth="150.0"
textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</children>
</HBox>
</bottom>
<center>
<PieChart fx:id="thisYearPieChart" BorderPane.alignment="CENTER"/>
</center>
<left>
<VBox alignment="CENTER" prefHeight="261.0" prefWidth="136.0" spacing="20.0"
BorderPane.alignment="CENTER">
<children>
<Label fx:id="thisYearOutputLabel" text="本年支出"/>
<Label fx:id="thisYearOutputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
<Label fx:id="thisYearInputLabel" text="本年收入"/>
<Label fx:id="thisYearInputShowLabel" textFill="#8bc065">
<font>
<Font size="30.0"/>
</font>
</Label>
</children>
</VBox>
</left>
<top>
<VBox alignment="CENTER" prefHeight="50.0" prefWidth="100.0"
BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="thisYearComboBox" onAction="#thisYearComboBoxEvent"
prefWidth="150.0"/>
</children>
</VBox>
</top>
</BorderPane>
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
接着在controller包下创建与之对应的控制器类ReportFrameController.java,从Scene Builder中复制该界面所用到的组件对象和事件方法代码到该类中:
package AccountSystem.controller;
import AccountSystem.bean.Session;
import AccountSystem.bean.User;
import AccountSystem.dao.RecordDao;
import AccountSystem.tools.DateTools;
import AccountSystem.tools.PublicTools;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.PieChart;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import java.util.Date;
public class ReportFrameController {
private PublicTools publicTools = new PublicTools();
private DateTools dateTools = new DateTools();
@FXML
private Label thisYearOutputShowLabel;
@FXML
private ComboBox<?> thisMonthComboBox;
@FXML
private Label thisDayInputShowLabel;
@FXML
private PieChart thisWeekPieChart;
@FXML
private ComboBox<?> thisDayComboBox;
@FXML
private ComboBox<?> thisYearComboBox;
@FXML
private Label thisMonthBalanceShowLabel;
@FXML
private Label thisSeasonBalanceShowLabel;
@FXML
private Label thisMonthOutputShowLabel;
@FXML
private Label thisDayBalanceShowLabel;
@FXML
private ComboBox<?> thisSeasonComboBox;
@FXML
private Label thisMonthInputShowLabel;
@FXML
private PieChart thisSeasonPieChart;
@FXML
private Label thisDayOutputShowLabel;
@FXML
private Label thisWeekInputShowLabel;
@FXML
private Label thisYearBalanceShowLabel;
@FXML
private PieChart thisYearPieChart;
@FXML
private Label thisYearInputShowLabel;
@FXML
private PieChart thisDayPieChart;
@FXML
private Label thisWeekOutputShowLabel;
@FXML
private Label thisWeekShowBalanceLabel;
@FXML
private ComboBox<?> thisWeekComboBox;
@FXML
private Label thisSeasonOutputShowLabel;
@FXML
private Label thisSeasonInputShowLabel;
@FXML
private PieChart thisMonthPieChart;
/**
* ”日报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisDayComboBoxEvent(ActionEvent event) {
}
/**
* ”周报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisWeekComboBoxEvent(ActionEvent event) {
}
/**
* ”月报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisMonthComboBoxEvent(ActionEvent event) {
}
/**
* ”季度报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisSeasonComboBoxEvent(ActionEvent event) {
}
/**
* ”年报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisYearComboBoxEvent(ActionEvent event) {
}
}
然后在MainApp.java中创建方法调用FXML资源文件:
/**
* 操作结果:“报告”查询结果界面
*/
public Scene initReportFrame() {
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/reportFrame.fxml"));
AnchorPane page = (AnchorPane) loader.load();
Stage mainFrameStage = new Stage();
mainFrameStage.setTitle("报告");
mainFrameStage.setResizable(true);
mainFrameStage.setAlwaysOnTop(false);
mainFrameStage.initModality(Modality.APPLICATION_MODAL);
mainFrameStage.initOwner(primaryStage);
Scene scene = new Scene(page);
mainFrameStage.setScene(scene);
mainFrameStage.showAndWait();
return scene;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
最后是在“报告”菜单项事件中进行调用显示界面,在MainPageController.java中:
/**
* “报告”菜单项的事件监听器
*
* @param event 事件
*/
@FXML
public void reportMenuItemEvent(ActionEvent event) {
// 打开报告界面
mainApp.initReportFrame();
}
运行程序,查看界面:
实现功能
在界面创建成功后,接下来就是实现具体的逻辑功能了。所需要实现的功能就是在不同的面板中的选择不同的下拉列表框选项,然后在面板界面显示支出、收入和余额的金额,并绘制一个饼图显示。
第一步:初始化下拉列表框的选项,即为所有的下拉列表框填充选项,将在initialize()方法中完成:
/**
* 初始化界面
*/
public void initialize() {
// 初始化填充下拉列表框选项
publicTools.public_addComboBoxItems(thisDayComboBox, new String[]{"本日"});
publicTools.public_addComboBoxItems(thisWeekComboBox, new String[]{"本周"});
publicTools.public_addComboBoxItems(thisMonthComboBox, new String[]{"本月"});
publicTools.public_addComboBoxItems(thisSeasonComboBox, new String[]{"本季度"});
publicTools.public_addComboBoxItems(thisYearComboBox, new String[]{"本年"});
}
这下就可以看到下拉列表框的选项了:
以“日报告”界面为例,先根据日期获取支出金额和收入金额,然后计算出余额,并且将其显示在界面的各个组件上。
所以下面三个方法分别是将数据填充到饼图上、设定报告界面的数据和计算余额的:
/**
* 操作结果:设置饼图
*
* @param pieChart 饼图
* @param input 收入总金额
* @param output 支出总金额
*/
private void setPieChartData(PieChart pieChart, float input, float output) {
// 创建集合ObservableList
ObservableList observableList = FXCollections.observableArrayList(
new PieChart.Data("收入", input),
new PieChart.Data("支出", output)
);
// 顺时针设置饼图的切片
pieChart.setClockwise(true);
// 方法设置标签行的长度
pieChart.setLabelLineLength(50);
// 将饼图的标签设置为可见
pieChart.setLabelsVisible(true);
// 设置饼图的起始角度
pieChart.setStartAngle(180);
// 为饼图填充数据
pieChart.setData(observableList);
}
/**
* 操作结果:设置报告界面饼图数据
*
* @param user 用户对象
* @param startDate 起始日期
* @param endDate 终止日期
* @param balance 余额
* @param pieChart 饼图
* @param outputShowLabel 支出显示标签
* @param inputShowLabel 收入显示标签
* @param balanceLabel 余额显示标签
*/
private void setReportFrame(User user, Date startDate, Date endDate, float balance, PieChart pieChart, Label outputShowLabel, Label inputShowLabel, Label balanceLabel) {
// 实例化RecordDao
RecordDao recordDao = new RecordDao();
// 将起始日期格式化处理
String thisStartDate = dateTools.dateFormat(startDate, "yyyy-MM-dd");
// 将终止日期格式化处理
String thisEndDate = dateTools.dateFormat(endDate, "yyyy-MM-dd");
// 拼接SQL语句查询收入
String thisInputsql = "select SUM(rMoney) from tb_records where rType='收入' and rDate between '" + thisStartDate + "'" + " and " + "'" + thisEndDate + "' and uId=" + user.getUserId() + ";";
// 拼接SQL语句查询支出
String thisOutputsql = "select SUM(rMoney) from tb_records where rType='支出' and rDate between '" + thisStartDate + "'" + " and " + "'" + thisEndDate + "' and uId=" + user.getUserId() + ";";
// 执行SQL语句获取收入
float thisInput = recordDao.getResultValueBySql(thisInputsql);
// 执行SQL语句获取支出
float thisOutput = recordDao.getResultValueBySql(thisOutputsql);
// 设置标签名称
outputShowLabel.setText(String.valueOf(thisOutput));
inputShowLabel.setText(String.valueOf(thisInput));
balanceLabel.setText(String.valueOf(balance));
// 为饼图填充数据
setPieChartData(pieChart, thisInput, thisOutput);
}
/**
* 操作结果:根据用户计算余额
*
* @param user 用户对象
* @return float 余额
*/
private float getBalanceByUsers(User user) {
// 实例化RecordDao对象
RecordDao recordDao = new RecordDao();
// 获取用户支出总额
float totalOutput = recordDao.getTotalAccount("支出", user.getUserId());
// 获取用户收入总额
float totalInput = recordDao.getTotalAccount("收入", user.getUserId());
// 计算并返回余额
return totalInput - totalOutput;
}
其他如“日报告“、”周报告“、”月报告“等界面,都是一样的,都是调用上面的两个方法进行处理,不同的是日期不一致。所以各个下拉列表框的处理事件代码如下:
/**
* ”日报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisDayComboBoxEvent(ActionEvent event) {
// 获取下拉列表框选中的选项
String selectedCoboboxItem = (String) thisDayComboBox.getSelectionModel().selectedItemProperty().getValue();
// 判断下拉列表框中的选项并进行处理
if (selectedCoboboxItem.equals("本日")) {
setReportFrame(Session.getUser()
, new Date()
, new Date()
, getBalanceByUsers(Session.getUser())
, thisDayPieChart
, thisDayOutputShowLabel
, thisDayInputShowLabel
, thisDayBalanceShowLabel);
}
}
/**
* ”周报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisWeekComboBoxEvent(ActionEvent event) {
// 获取下拉列表框选中的选项
String selectedCoboboxItem = (String) thisWeekComboBox.getSelectionModel().selectedItemProperty().getValue();
if (selectedCoboboxItem.equals("本周")) {
setReportFrame(Session.getUser()
, dateTools.getWeekDayStartTime(new Date())
, dateTools.getWeekDayEndTime(new Date())
, getBalanceByUsers(Session.getUser())
, thisWeekPieChart
, thisWeekOutputShowLabel
, thisWeekInputShowLabel
, thisWeekShowBalanceLabel);
}
}
/**
* ”月报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisMonthComboBoxEvent(ActionEvent event) {
// 获取下拉列表框选中的选项
String selectedCoboboxItem = (String) thisMonthComboBox.getSelectionModel().selectedItemProperty().getValue();
if (selectedCoboboxItem.equals("本月")) {
setReportFrame(Session.getUser()
, dateTools.getMonthStartTime(new Date())
, dateTools.getMonthEndTime(new Date())
, getBalanceByUsers(Session.getUser())
, thisMonthPieChart
, thisMonthOutputShowLabel
, thisMonthInputShowLabel
, thisMonthBalanceShowLabel);
}
}
/**
* ”季度报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisSeasonComboBoxEvent(ActionEvent event) {
// 获取下拉列表框选中的选项
String selectedCoboboxItem = (String) thisSeasonComboBox.getSelectionModel().selectedItemProperty().getValue();
if (selectedCoboboxItem.equals("本季度")) {
setReportFrame(Session.getUser()
, dateTools.getQuarterStartTime(new Date())
, dateTools.getQuarterEndTime(new Date())
, getBalanceByUsers(Session.getUser())
, thisSeasonPieChart
, thisSeasonOutputShowLabel
, thisSeasonInputShowLabel
, thisSeasonBalanceShowLabel);
}
}
/**
* ”年报告“界面的下拉列表框的事件监听器
*
* @param event 事件
*/
public void thisYearComboBoxEvent(ActionEvent event) {
// 获取下拉列表框选中的选项
String selectedCoboboxItem = (String) thisYearComboBox.getSelectionModel().selectedItemProperty().getValue();
if (selectedCoboboxItem.equals("本年")) {
setReportFrame(Session.getUser()
, dateTools.getYearStartTime(new Date())
, dateTools.getYearEndTime(new Date())
, getBalanceByUsers(Session.getUser())
, thisYearPieChart
, thisYearOutputShowLabel
, thisYearInputShowLabel
, thisYearBalanceShowLabel);
}
}
看上面的代码各个下拉列表框的事件处理都是类似的,不同的是起始日期和结束日期。
所以现在可以测试功能了:
可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。
注意:在公众号后台回复【20200418】可获取本章的源码。